Skip to content

Commit c17c7f2

Browse files
committed
Isolate builders into files and implement attribute support
1 parent f615296 commit c17c7f2

File tree

7 files changed

+188
-201
lines changed

7 files changed

+188
-201
lines changed

postgres_resource_derive/src/attr.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
1-
use proc_macro2::{Span, TokenTree::Literal};
21
use syn::{
32
parse::{Parse, ParseStream, Result},
4-
punctuated::Punctuated,
5-
token, Attribute, Ident, LitStr,
3+
Attribute, Error, Lit, LitStr,
64
Meta::*,
75
MetaNameValue,
8-
Error,
9-
Lit,
106
};
117

128
#[derive(Debug)]
139
pub struct Attrs {
14-
db_conn: Option<LitStr>,
15-
table: Option<LitStr>,
10+
pub db_conn: Option<LitStr>,
11+
pub table: Option<LitStr>,
1612
}
1713

1814
impl Parse for Attrs {
@@ -31,18 +27,14 @@ impl Parse for Attrs {
3127
}
3228
}
3329

34-
println!("{:#?}", table);
35-
3630
Ok(Attrs { db_conn, table })
3731
}
3832
}
3933

4034
impl Attrs {
4135
fn parse_attr(attr: &Attribute, expected: &str) -> Result<Option<LitStr>> {
4236
match attr.parse_meta()? {
43-
NameValue(MetaNameValue { lit: Lit::Str(lit_str), .. }) => {
44-
Ok(Some(lit_str))
45-
}
37+
NameValue(MetaNameValue { lit: Lit::Str(lit_str), .. }) => Ok(Some(lit_str)),
4638
_ => {
4739
let error_span = attr.bracket_token.span;
4840
let message = &format!("expected #[{} = \"...\"]", expected);
@@ -51,4 +43,3 @@ impl Attrs {
5143
}
5244
}
5345
}
54-
Lines changed: 12 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
1-
use crate::{attr::*, IdentExt, camel_to_snake, r#struct::*, AsSnake};
1+
use crate::{camel_to_snake, r#struct::*, AsSnake};
22

33
use proc_macro2::Span;
4-
use syn::{
5-
parse::{Parse, ParseStream, Result},
6-
punctuated::Punctuated,
7-
token, Attribute, Ident, LitStr,
8-
Meta::*,
9-
MetaNameValue,
10-
Index,
11-
};
4+
use syn::{parse::Result, LitStr};
125

136
pub struct Input {
147
pub parsed_struct: Struct,
@@ -18,7 +11,7 @@ pub trait Builder<'i> {
1811
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream>;
1912
}
2013

21-
pub struct InferredTableMacro;
14+
struct InferredTableMacro;
2215

2316
impl<'i> Builder<'i> for InferredTableMacro {
2417
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
@@ -28,172 +21,23 @@ impl<'i> Builder<'i> for InferredTableMacro {
2821
}
2922
}
3023

31-
pub struct CustomTableMacro<B>(pub B);
24+
pub struct TableMacro;
3225

33-
impl<'i, B: Builder<'i>> Builder<'i> for CustomTableMacro<B> {
26+
impl<'i> Builder<'i> for TableMacro {
3427
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
35-
self.0.build(input)
28+
if let Some(ref table) = input.parsed_struct.attrs.table {
29+
Ok(quote!(#[table_name = #table]))
30+
} else {
31+
Ok(InferredTableMacro.build(input)?)
32+
}
3633
}
3734
}
3835

39-
pub struct ModelWithId;
36+
pub struct Schema;
4037

41-
impl<'i> Builder<'i> for ModelWithId {
42-
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
43-
let model_name_with_id = input.parsed_struct.ident.append("WithId");
44-
let fields = ModelWithIdFields.build(input)?;
45-
46-
Ok(quote! {
47-
pub struct #model_name_with_id {
48-
#fields
49-
}
50-
})
51-
}
52-
}
53-
54-
pub struct ModelWithIdFields;
55-
56-
impl<'i> Builder<'i> for ModelWithIdFields {
57-
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
58-
let mut fields = Vec::new();
59-
fields.push(quote!(pub id: i32));
60-
61-
let model_name = &input.parsed_struct.ident;
62-
fields.push(quote!(pub inner: #model_name));
63-
64-
input.parsed_struct.fields.iter().for_each(|field| {
65-
if field.fk() {
66-
let ty = field.ty();
67-
let name = &field.name;
68-
fields.push(quote!(pub #name: #ty));
69-
}
70-
});
71-
72-
Ok(quote!(#(#fields,)*))
73-
}
74-
}
75-
76-
pub struct Model;
77-
78-
impl<'i> Builder<'i> for Model {
79-
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
80-
let model_name = &input.parsed_struct.ident;
81-
let fields = ModelFields.build(input)?;
82-
83-
Ok(quote! {
84-
pub struct #model_name {
85-
#fields
86-
}
87-
})
88-
}
89-
}
90-
91-
pub struct ModelFields;
92-
93-
impl<'i> Builder<'i> for ModelFields {
94-
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
95-
let mut fields = Vec::new();
96-
input.parsed_struct.fields.iter().for_each(|field| {
97-
if !field.fk() {
98-
let ty = field.ty();
99-
let name = &field.name;
100-
fields.push(quote!(pub #name: #ty));
101-
}
102-
});
103-
104-
Ok(quote!(#(#fields,)*))
105-
}
106-
}
107-
108-
pub struct Table;
109-
110-
impl<'i> Builder<'i> for Table {
38+
impl<'i> Builder<'i> for Schema {
11139
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
11240
let model = input.parsed_struct.as_snake_plural();
11341
Ok(quote!(crate::schema::#model))
11442
}
11543
}
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-

postgres_resource_derive/src/field.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use syn::{
22
parse::{Parse, ParseStream, Result},
3-
punctuated::Punctuated,
4-
token, Attribute, Ident,
3+
Attribute, Ident,
54
};
65

76
#[derive(Debug, PartialEq)]

postgres_resource_derive/src/lib.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,13 @@ mod attr;
1414
mod builder;
1515
mod field;
1616
mod r#struct;
17+
mod model;
18+
mod queryable;
1719

18-
use crate::{attr::*, builder::*, field::*, r#struct::*};
20+
use crate::{model::*, queryable::*, builder::*, r#struct::*};
1921

2022
use proc_macro2::Span;
21-
use syn::{
22-
parse::{Parse, ParseStream, Result},
23-
punctuated::Punctuated,
24-
token, Attribute, Ident,
25-
};
23+
use syn::{parse::Result, Ident};
2624

2725
trait IdentExt {
2826
fn append(&self, string: &str) -> Ident;
@@ -61,7 +59,7 @@ impl Input {
6159
}
6260

6361
fn gen_model(&self) -> Result<proc_macro2::TokenStream> {
64-
let table_macro = InferredTableMacro.build(&self)?;
62+
let table_macro = TableMacro.build(&self)?;
6563
let model_with_id = ModelWithId.build(&self)?;
6664
let model = Model.build(&self)?;
6765

@@ -75,13 +73,13 @@ impl Input {
7573
#model
7674
})
7775
}
78-
76+
7977
fn gen_controller(&self) -> Result<proc_macro2::TokenStream> {
80-
let model_with_id = self.parsed_struct.model_name();
78+
let model_with_id = self.parsed_struct.model_name_with_id();
8179
let model = self.parsed_struct.inner_model_name();
8280
let controller = self.parsed_struct.controller_name();
8381

84-
let schema = Table.build(&self)?;
82+
let schema = Schema.build(&self)?;
8583

8684
let connection = quote!(&self.connection());
8785

@@ -134,7 +132,7 @@ impl Input {
134132
})
135133
}
136134
}
137-
//
135+
138136
///
139137
/// ### Model Definition
140138
/// ```

postgres_resource_derive/src/model.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use crate::builder::{Input, Builder};
2+
3+
use syn::parse::Result;
4+
5+
pub struct ModelWithId;
6+
7+
impl<'i> Builder<'i> for ModelWithId {
8+
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
9+
let model_name_with_id = input.parsed_struct.model_name_with_id();
10+
let fields = ModelWithIdFields.build(input)?;
11+
12+
Ok(quote! {
13+
pub struct #model_name_with_id {
14+
#fields
15+
}
16+
})
17+
}
18+
}
19+
20+
struct ModelWithIdFields;
21+
22+
impl<'i> Builder<'i> for ModelWithIdFields {
23+
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
24+
let mut fields = Vec::new();
25+
fields.push(quote!(pub id: i32));
26+
27+
let model_name = &input.parsed_struct.ident;
28+
fields.push(quote!(pub inner: #model_name));
29+
30+
input.parsed_struct.fields.iter().for_each(|field| {
31+
if field.fk() {
32+
let ty = field.ty();
33+
let name = &field.name;
34+
fields.push(quote!(pub #name: #ty));
35+
}
36+
});
37+
38+
Ok(quote!(#(#fields,)*))
39+
}
40+
}
41+
42+
pub struct Model;
43+
44+
impl<'i> Builder<'i> for Model {
45+
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
46+
let model_name = &input.parsed_struct.ident;
47+
let fields = ModelFields.build(input)?;
48+
49+
Ok(quote! {
50+
pub struct #model_name {
51+
#fields
52+
}
53+
})
54+
}
55+
}
56+
57+
struct ModelFields;
58+
59+
impl<'i> Builder<'i> for ModelFields {
60+
fn build(self, input: &'i Input) -> Result<proc_macro2::TokenStream> {
61+
let mut fields = Vec::new();
62+
input.parsed_struct.fields.iter().for_each(|field| {
63+
if !field.fk() {
64+
let ty = field.ty();
65+
let name = &field.name;
66+
fields.push(quote!(pub #name: #ty));
67+
}
68+
});
69+
70+
Ok(quote!(#(#fields,)*))
71+
}
72+
}
73+

0 commit comments

Comments
 (0)