Skip to content
This repository was archived by the owner on Oct 10, 2019. It is now read-only.

Commit e89a9a5

Browse files
committed
Finish switch to quote!
Closes #2
1 parent edeff98 commit e89a9a5

File tree

3 files changed

+161
-163
lines changed

3 files changed

+161
-163
lines changed
Lines changed: 82 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use std::fmt::Write;
1+
use std::iter;
22
use syn::{self, Body, Ident, MacroInput, VariantData};
3-
use quote::{Tokens, ToTokens};
3+
use quote::Tokens;
44

55
use accepts;
66
use composites::Field;
@@ -15,15 +15,15 @@ pub fn expand_derive_fromsql(input: &MacroInput) -> Result<String, String> {
1515
let (accepts_body, to_sql_body) = match input.body {
1616
Body::Enum(ref variants) => {
1717
let variants: Vec<Variant> = try!(variants.iter().map(Variant::parse).collect());
18-
(accepts::enum_body(&name, &variants).to_string(), enum_body(&input.ident, &variants))
18+
(accepts::enum_body(&name, &variants), enum_body(&input.ident, &variants))
1919
}
2020
Body::Struct(VariantData::Tuple(ref fields)) if fields.len() == 1 => {
2121
let field = &fields[0];
2222
(domain_accepts_body(field), domain_body(&input.ident, field))
2323
}
2424
Body::Struct(VariantData::Struct(ref fields)) => {
2525
let fields: Vec<Field> = try!(fields.iter().map(Field::parse).collect());
26-
(accepts::composite_body(&name, "FromSql", &fields).to_string(),
26+
(accepts::composite_body(&name, "FromSql", &fields),
2727
composite_body(&input.ident, &fields))
2828
}
2929
_ => {
@@ -32,86 +32,92 @@ pub fn expand_derive_fromsql(input: &MacroInput) -> Result<String, String> {
3232
}
3333
};
3434

35-
let out = format!("
36-
impl ::postgres::types::FromSql for {} {{
37-
fn from_sql(_type: &::postgres::types::Type,
38-
buf: &[u8],
39-
_info: &::postgres::types::SessionInfo)
40-
-> ::std::result::Result<{},
41-
::std::boxed::Box<::std::error::Error +
42-
::std::marker::Sync +
43-
::std::marker::Send>> {{{}
44-
}}
45-
46-
fn accepts(type_: &::postgres::types::Type) -> bool {{{}
47-
}}
48-
}}", input.ident, input.ident, to_sql_body, accepts_body);
49-
50-
Ok(out)
51-
}
35+
let ident = &input.ident;
36+
let out = quote! {
37+
impl ::postgres::types::FromSql for #ident {
38+
fn from_sql(_type: &::postgres::types::Type,
39+
buf: &[u8],
40+
_info: &::postgres::types::SessionInfo)
41+
-> ::std::result::Result<#ident,
42+
::std::boxed::Box<::std::error::Error +
43+
::std::marker::Sync +
44+
::std::marker::Send>> {
45+
#to_sql_body
46+
}
5247

53-
fn enum_body(ident: &Ident, variants: &[Variant]) -> String {
54-
let mut out = "
55-
match buf {".to_owned();
48+
fn accepts(type_: &::postgres::types::Type) -> bool {
49+
#accepts_body
50+
}
51+
}
52+
};
5653

57-
for variant in variants {
58-
write!(out, "
59-
b\"{}\" => Ok({}::{}),", variant.name, ident, variant.ident).unwrap();
60-
}
54+
Ok(out.to_string())
55+
}
56+
57+
fn enum_body(ident: &Ident, variants: &[Variant]) -> Tokens {
58+
let variant_names = variants.iter().map(|v| &v.name);
59+
let idents = iter::repeat(ident);
60+
let variant_idents = variants.iter().map(|v| &v.ident);
6161

62-
out.push_str("
62+
quote! {
63+
match try!(::std::str::from_utf8(buf)) {
64+
#(
65+
#variant_names => ::std::result::Result::Ok(#idents::#variant_idents),
66+
)*
6367
s => {
6468
::std::result::Result::Err(
65-
::std::convert::Into::into(format!(\"invalid variant `{}`\",
66-
::std::string::String::from_utf8_lossy(s))))
69+
::std::convert::Into::into(format!("invalid variant `{}`", s)))
6770
}
68-
}");
69-
70-
out
71+
}
72+
}
7173
}
7274

73-
fn domain_accepts_body(field: &syn::Field) -> String {
74-
let mut tokens = Tokens::new();
75-
field.ty.to_tokens(&mut tokens);
76-
format!("
77-
<{} as ::postgres::types::FromSql>::accepts(type_)", tokens)
75+
fn domain_accepts_body(field: &syn::Field) -> Tokens {
76+
let ty = &field.ty;
77+
quote! {
78+
<#ty as ::postgres::types::FromSql>::accepts(type_)
79+
}
7880
}
7981

80-
fn domain_body(ident: &Ident, field: &syn::Field) -> String {
81-
let mut tokens = Tokens::new();
82-
field.ty.to_tokens(&mut tokens);
83-
format!("\
84-
<{} as ::postgres::types::FromSql>::from_sql(_type, buf, _info).map({})", tokens, ident)
82+
fn domain_body(ident: &Ident, field: &syn::Field) -> Tokens {
83+
let ty = &field.ty;
84+
quote! {
85+
<#ty as ::postgres::types::FromSql>::from_sql(_type, buf, _info).map(#ident)
86+
}
8587
}
8688

87-
fn composite_body(ident: &Ident, fields: &[Field]) -> String {
88-
let mut out = "
89+
fn composite_body(ident: &Ident, fields: &[Field]) -> Tokens {
90+
let temp_vars = &fields.iter().map(|f| Ident::new(format!("__{}", f.ident))).collect::<Vec<_>>();
91+
let field_names = &fields.iter().map(|f| &f.name).collect::<Vec<_>>();
92+
let field_idents = &fields.iter().map(|f| &f.ident).collect::<Vec<_>>();
93+
94+
quote! {
8995
fn read_be_i32(buf: &mut &[u8]) -> ::std::io::Result<i32> {
9096
let mut bytes = [0; 4];
9197
try!(::std::io::Read::read_exact(buf, &mut bytes));
9298
let num = ((bytes[0] as i32) << 24) |
93-
((bytes[1] as i32) << 16) |
94-
((bytes[2] as i32) << 8) |
95-
(bytes[3] as i32);
99+
((bytes[1] as i32) << 16) |
100+
((bytes[2] as i32) << 8) |
101+
(bytes[3] as i32);
96102
::std::result::Result::Ok(num)
97103
}
98104

99105
fn read_value<T>(type_: &::postgres::types::Type,
100106
buf: &mut &[u8],
101107
info: &::postgres::types::SessionInfo)
102108
-> ::std::result::Result<T,
103-
::std::boxed::Box<::std::error::Error +
104-
::std::marker::Sync +
105-
::std::marker::Send>>
106-
where T: ::postgres::types::FromSql
109+
::std::boxed::Box<::std::error::Error +
110+
::std::marker::Sync +
111+
::std::marker::Send>>
112+
where T: ::postgres::types::FromSql
107113
{
108114
let len = try!(read_be_i32(buf));
109115
let value = if len < 0 {
110116
::std::option::Option::None
111117
} else {
112118
if len as usize > buf.len() {
113119
return ::std::result::Result::Err(
114-
::std::convert::Into::into(\"invalid buffer size\"));
120+
::std::convert::Into::into("invalid buffer size"));
115121
}
116122
let (head, tail) = buf.split_at(len as usize);
117123
*buf = tail;
@@ -129,49 +135,35 @@ fn composite_body(ident: &Ident, fields: &[Field]) -> String {
129135
let num_fields = try!(read_be_i32(&mut buf));
130136
if num_fields as usize != fields.len() {
131137
return ::std::result::Result::Err(
132-
::std::convert::Into::into(format!(\"invalid field count: {} vs {}\", num_fields,
138+
::std::convert::Into::into(format!("invalid field count: {} vs {}", num_fields,
133139
fields.len())));
134140
}
135-
".to_owned();
136141

137-
for field in fields {
138-
write!(out, "
139-
let mut __{} = ::std::option::Option::None;", field.ident).unwrap();
140-
}
142+
#(
143+
let mut #temp_vars = ::std::option::Option::None;
144+
)*
141145

142-
write!(out, "
143-
for field in fields {{
146+
for field in fields {
144147
let oid = try!(read_be_i32(&mut buf)) as u32;
145-
if oid != field.type_().oid() {{
146-
return ::std::result::Result::Err(
147-
::std::convert::Into::into(\"unexpected OID\"));
148-
}}
149-
150-
match field.name() {{").unwrap();
151-
152-
for field in fields {
153-
write!(out, "
154-
\"{}\" => {{
155-
__{} = ::std::option::Option::Some(
156-
try!(read_value(field.type_(), &mut buf, _info)));
157-
}}",
158-
field.name, field.ident).unwrap();
159-
}
148+
if oid != field.type_().oid() {
149+
return ::std::result::Result::Err(::std::convert::Into::into("unexpected OID"));
150+
}
160151

161-
write!(out, "
152+
match field.name() {
153+
#(
154+
#field_names => {
155+
#temp_vars = ::std::option::Option::Some(
156+
try!(read_value(field.type_(), &mut buf, _info)));
157+
}
158+
)*
162159
_ => unreachable!(),
163-
}}
164-
}}
165-
166-
::std::result::Result::Ok({} {{", ident).unwrap();
160+
}
161+
}
167162

168-
for field in fields {
169-
write!(out, "
170-
{}: __{}.unwrap(),", field.ident, field.ident).unwrap();
163+
::std::result::Result::Ok(#ident {
164+
#(
165+
#field_idents: #temp_vars.unwrap(),
166+
)*
167+
})
171168
}
172-
173-
write!(out, "
174-
}})").unwrap();
175-
176-
out
177169
}

postgres-derive-internals/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![recursion_limit = "128"]
1+
#![recursion_limit = "256"]
22
extern crate syn;
33
#[macro_use]
44
extern crate quote;

0 commit comments

Comments
 (0)