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

Commit e47a4ac

Browse files
committed
Add FromSql lifetime support
1 parent 1642ea5 commit e47a4ac

File tree

6 files changed

+26
-17
lines changed

6 files changed

+26
-17
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ proc-macro = true
1313
test = false
1414

1515
[dependencies]
16+
proc-macro2 = "0.3"
1617
syn = "0.13"
1718
quote = "0.5"
1819

1920
[dev-dependencies]
20-
postgres = "0.15.1"
21+
postgres = { git = "https://github.com/sfackler/rust-postgres" }

src/accepts.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::iter;
2-
use syn::Ident;
2+
use syn::{Ident, Lifetime};
33
use quote::Tokens;
44

55
use enums::Variant;
@@ -34,13 +34,17 @@ pub fn enum_body(name: &str, variants: &[Variant]) -> Tokens {
3434
}
3535
}
3636

37-
pub fn composite_body(name: &str, trait_: &str, fields: &[Field]) -> Tokens {
37+
pub fn composite_body(name: &str, trait_: &str, lifetime: Option<Lifetime>, fields: &[Field]) -> Tokens {
3838
let num_fields = fields.len();
3939
let trait_ = Ident::from(trait_);
40-
let traits = iter::repeat(&trait_);
4140
let field_names = fields.iter().map(|f| &f.name);
4241
let field_types = fields.iter().map(|f| &f.type_);
4342

43+
let trait_tokens = iter::repeat(match lifetime {
44+
Some(lifetime) => quote!{ ::postgres::types::#trait_<#lifetime> },
45+
None => quote! { ::postgres::types::#trait_ },
46+
});
47+
4448
quote! {
4549
if type_.name() != #name {
4650
return false;
@@ -56,7 +60,7 @@ pub fn composite_body(name: &str, trait_: &str, fields: &[Field]) -> Tokens {
5660
match f.name() {
5761
#(
5862
#field_names => {
59-
<#field_types as ::postgres::types::#traits>::accepts(f.type_())
63+
<#field_types as #trait_tokens>::accepts(f.type_())
6064
}
6165
)*
6266
_ => false,

src/fromsql.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
use proc_macro2::Span;
12
use std::iter;
2-
use syn::{self, Ident, DeriveInput, Data, DataStruct, Fields};
3+
use syn::{self, Ident, DeriveInput, Data, DataStruct, Fields, Lifetime};
34
use quote::Tokens;
45

56
use accepts;
@@ -12,6 +13,8 @@ pub fn expand_derive_fromsql(input: DeriveInput) -> Result<Tokens, String> {
1213

1314
let name = overrides.name.unwrap_or_else(|| input.ident.to_string());
1415

16+
let trait_lifetime = Lifetime::new("'from_sql", Span::call_site());
17+
1518
let (accepts_body, to_sql_body) = match input.data {
1619
Data::Enum(ref data) => {
1720
let variants = data.variants.iter().map(Variant::parse).collect::<Result<Vec<_>, _>>()?;
@@ -23,18 +26,18 @@ pub fn expand_derive_fromsql(input: DeriveInput) -> Result<Tokens, String> {
2326
}
2427
Data::Struct(DataStruct { fields: Fields::Named(ref fields), .. }) => {
2528
let fields = fields.named.iter().map(Field::parse).collect::<Result<Vec<_>, _>>()?;
26-
(accepts::composite_body(&name, "FromSql", &fields),
27-
composite_body(&input.ident, &fields))
29+
(accepts::composite_body(&name, "FromSql", Some(trait_lifetime), &fields),
30+
composite_body(&input.ident, trait_lifetime, &fields))
2831
}
2932
_ => {
30-
return Err("#[derive(ToSql)] may only be applied to structs, single field tuple \
33+
return Err("#[derive(FromSql)] may only be applied to structs, single field tuple \
3134
structs, and enums".to_owned())
3235
}
3336
};
3437

3538
let ident = &input.ident;
3639
let out = quote! {
37-
impl ::postgres::types::FromSql for #ident {
40+
impl<#trait_lifetime> ::postgres::types::FromSql<#trait_lifetime> for #ident {
3841
fn from_sql(_type: &::postgres::types::Type,
3942
buf: &[u8])
4043
-> ::std::result::Result<#ident,
@@ -85,7 +88,7 @@ fn domain_body(ident: &Ident, field: &syn::Field) -> Tokens {
8588
}
8689
}
8790

88-
fn composite_body(ident: &Ident, fields: &[Field]) -> Tokens {
91+
fn composite_body(ident: &Ident, lifetime: syn::Lifetime, fields: &[Field]) -> Tokens {
8992
let temp_vars = &fields.iter().map(|f| Ident::from(format!("__{}", f.ident))).collect::<Vec<_>>();
9093
let field_names = &fields.iter().map(|f| &f.name).collect::<Vec<_>>();
9194
let field_idents = &fields.iter().map(|f| &f.ident).collect::<Vec<_>>();
@@ -101,13 +104,13 @@ fn composite_body(ident: &Ident, fields: &[Field]) -> Tokens {
101104
::std::result::Result::Ok(num)
102105
}
103106

104-
fn read_value<T>(type_: &::postgres::types::Type,
105-
buf: &mut &[u8])
107+
fn read_value<#lifetime, T>(type_: &::postgres::types::Type,
108+
buf: &#lifetime mut &[u8])
106109
-> ::std::result::Result<T,
107110
::std::boxed::Box<::std::error::Error +
108111
::std::marker::Sync +
109112
::std::marker::Send>>
110-
where T: ::postgres::types::FromSql
113+
where T: ::postgres::types::FromSql<#lifetime>
111114
{
112115
let len = read_be_i32(buf)?;
113116
let value = if len < 0 {

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![recursion_limit = "256"]
22

33
extern crate proc_macro;
4+
extern crate proc_macro2;
45
extern crate syn;
56
#[macro_use]
67
extern crate quote;

src/tosql.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub fn expand_derive_tosql(input: DeriveInput) -> Result<Tokens, String> {
2323
}
2424
Data::Struct(DataStruct { fields: Fields::Named(ref fields), .. }) => {
2525
let fields = fields.named.iter().map(Field::parse).collect::<Result<Vec<_>, _>>()?;
26-
(accepts::composite_body(&name, "ToSql", &fields),
26+
(accepts::composite_body(&name, "ToSql", None, &fields),
2727
composite_body(&fields))
2828
}
2929
_ => {

tests/util/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use postgres::types::{FromSql, ToSql};
1+
use postgres::types::{FromSqlOwned, ToSql};
22
use postgres::Connection;
33
use std::fmt;
44

55
pub fn test_type<T, S>(conn: &Connection, sql_type: &str, checks: &[(T, S)])
66
where
7-
T: PartialEq + FromSql + ToSql,
7+
T: PartialEq + FromSqlOwned + ToSql,
88
S: fmt::Display,
99
{
1010
for &(ref val, ref repr) in checks.iter() {

0 commit comments

Comments
 (0)