From e47a4acb674ad32b3a41093c0459d558d53fa28d Mon Sep 17 00:00:00 2001 From: Artem Vorotnikov Date: Thu, 31 May 2018 10:40:45 +0300 Subject: [PATCH 1/2] Add FromSql lifetime support --- Cargo.toml | 3 ++- src/accepts.rs | 12 ++++++++---- src/fromsql.rs | 21 ++++++++++++--------- src/lib.rs | 1 + src/tosql.rs | 2 +- tests/util/mod.rs | 4 ++-- 6 files changed, 26 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9035a5b..af670e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,8 +13,9 @@ proc-macro = true test = false [dependencies] +proc-macro2 = "0.3" syn = "0.13" quote = "0.5" [dev-dependencies] -postgres = "0.15.1" +postgres = { git = "https://github.com/sfackler/rust-postgres" } diff --git a/src/accepts.rs b/src/accepts.rs index 04310ee..d792347 100644 --- a/src/accepts.rs +++ b/src/accepts.rs @@ -1,5 +1,5 @@ use std::iter; -use syn::Ident; +use syn::{Ident, Lifetime}; use quote::Tokens; use enums::Variant; @@ -34,13 +34,17 @@ pub fn enum_body(name: &str, variants: &[Variant]) -> Tokens { } } -pub fn composite_body(name: &str, trait_: &str, fields: &[Field]) -> Tokens { +pub fn composite_body(name: &str, trait_: &str, lifetime: Option, fields: &[Field]) -> Tokens { let num_fields = fields.len(); let trait_ = Ident::from(trait_); - let traits = iter::repeat(&trait_); let field_names = fields.iter().map(|f| &f.name); let field_types = fields.iter().map(|f| &f.type_); + let trait_tokens = iter::repeat(match lifetime { + Some(lifetime) => quote!{ ::postgres::types::#trait_<#lifetime> }, + None => quote! { ::postgres::types::#trait_ }, + }); + quote! { if type_.name() != #name { return false; @@ -56,7 +60,7 @@ pub fn composite_body(name: &str, trait_: &str, fields: &[Field]) -> Tokens { match f.name() { #( #field_names => { - <#field_types as ::postgres::types::#traits>::accepts(f.type_()) + <#field_types as #trait_tokens>::accepts(f.type_()) } )* _ => false, diff --git a/src/fromsql.rs b/src/fromsql.rs index 40373f3..9cd702e 100644 --- a/src/fromsql.rs +++ b/src/fromsql.rs @@ -1,5 +1,6 @@ +use proc_macro2::Span; use std::iter; -use syn::{self, Ident, DeriveInput, Data, DataStruct, Fields}; +use syn::{self, Ident, DeriveInput, Data, DataStruct, Fields, Lifetime}; use quote::Tokens; use accepts; @@ -12,6 +13,8 @@ pub fn expand_derive_fromsql(input: DeriveInput) -> Result { let name = overrides.name.unwrap_or_else(|| input.ident.to_string()); + let trait_lifetime = Lifetime::new("'from_sql", Span::call_site()); + let (accepts_body, to_sql_body) = match input.data { Data::Enum(ref data) => { let variants = data.variants.iter().map(Variant::parse).collect::, _>>()?; @@ -23,18 +26,18 @@ pub fn expand_derive_fromsql(input: DeriveInput) -> Result { } Data::Struct(DataStruct { fields: Fields::Named(ref fields), .. }) => { let fields = fields.named.iter().map(Field::parse).collect::, _>>()?; - (accepts::composite_body(&name, "FromSql", &fields), - composite_body(&input.ident, &fields)) + (accepts::composite_body(&name, "FromSql", Some(trait_lifetime), &fields), + composite_body(&input.ident, trait_lifetime, &fields)) } _ => { - return Err("#[derive(ToSql)] may only be applied to structs, single field tuple \ + return Err("#[derive(FromSql)] may only be applied to structs, single field tuple \ structs, and enums".to_owned()) } }; let ident = &input.ident; let out = quote! { - impl ::postgres::types::FromSql for #ident { + impl<#trait_lifetime> ::postgres::types::FromSql<#trait_lifetime> for #ident { fn from_sql(_type: &::postgres::types::Type, buf: &[u8]) -> ::std::result::Result<#ident, @@ -85,7 +88,7 @@ fn domain_body(ident: &Ident, field: &syn::Field) -> Tokens { } } -fn composite_body(ident: &Ident, fields: &[Field]) -> Tokens { +fn composite_body(ident: &Ident, lifetime: syn::Lifetime, fields: &[Field]) -> Tokens { let temp_vars = &fields.iter().map(|f| Ident::from(format!("__{}", f.ident))).collect::>(); let field_names = &fields.iter().map(|f| &f.name).collect::>(); let field_idents = &fields.iter().map(|f| &f.ident).collect::>(); @@ -101,13 +104,13 @@ fn composite_body(ident: &Ident, fields: &[Field]) -> Tokens { ::std::result::Result::Ok(num) } - fn read_value(type_: &::postgres::types::Type, - buf: &mut &[u8]) + fn read_value<#lifetime, T>(type_: &::postgres::types::Type, + buf: &#lifetime mut &[u8]) -> ::std::result::Result> - where T: ::postgres::types::FromSql + where T: ::postgres::types::FromSql<#lifetime> { let len = read_be_i32(buf)?; let value = if len < 0 { diff --git a/src/lib.rs b/src/lib.rs index 7f2964a..202293b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ #![recursion_limit = "256"] extern crate proc_macro; +extern crate proc_macro2; extern crate syn; #[macro_use] extern crate quote; diff --git a/src/tosql.rs b/src/tosql.rs index 4ea89ab..f45db02 100644 --- a/src/tosql.rs +++ b/src/tosql.rs @@ -23,7 +23,7 @@ pub fn expand_derive_tosql(input: DeriveInput) -> Result { } Data::Struct(DataStruct { fields: Fields::Named(ref fields), .. }) => { let fields = fields.named.iter().map(Field::parse).collect::, _>>()?; - (accepts::composite_body(&name, "ToSql", &fields), + (accepts::composite_body(&name, "ToSql", None, &fields), composite_body(&fields)) } _ => { diff --git a/tests/util/mod.rs b/tests/util/mod.rs index f44d98a..9893ae7 100644 --- a/tests/util/mod.rs +++ b/tests/util/mod.rs @@ -1,10 +1,10 @@ -use postgres::types::{FromSql, ToSql}; +use postgres::types::{FromSqlOwned, ToSql}; use postgres::Connection; use std::fmt; pub fn test_type(conn: &Connection, sql_type: &str, checks: &[(T, S)]) where - T: PartialEq + FromSql + ToSql, + T: PartialEq + FromSqlOwned + ToSql, S: fmt::Display, { for &(ref val, ref repr) in checks.iter() { From 5385035859e55f73f6c89e761510c891243e0977 Mon Sep 17 00:00:00 2001 From: Artem Vorotnikov Date: Fri, 22 Feb 2019 01:20:40 +0300 Subject: [PATCH 2/2] 2018 edition --- Cargo.toml | 1 + src/accepts.rs | 4 ++-- src/composites.rs | 2 +- src/enums.rs | 2 +- src/fromsql.rs | 8 ++++---- src/lib.rs | 4 +--- src/tosql.rs | 8 ++++---- 7 files changed, 14 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index af670e1..0bdeee4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "postgres-derive" version = "0.3.3" +edition = "2018" authors = ["Steven Fackler "] license = "MIT/Apache-2.0" description = "Deriving plugin support for Postgres enum, domain, and composite types" diff --git a/src/accepts.rs b/src/accepts.rs index d792347..483d7f0 100644 --- a/src/accepts.rs +++ b/src/accepts.rs @@ -2,8 +2,8 @@ use std::iter; use syn::{Ident, Lifetime}; use quote::Tokens; -use enums::Variant; -use composites::Field; +use crate::enums::Variant; +use crate::composites::Field; pub fn enum_body(name: &str, variants: &[Variant]) -> Tokens { let num_variants = variants.len(); diff --git a/src/composites.rs b/src/composites.rs index f58cbd9..413b518 100644 --- a/src/composites.rs +++ b/src/composites.rs @@ -1,6 +1,6 @@ use syn::{self, Ident, Type}; -use overrides::Overrides; +use crate::overrides::Overrides; pub struct Field { pub name: String, diff --git a/src/enums.rs b/src/enums.rs index d213e0a..172e378 100644 --- a/src/enums.rs +++ b/src/enums.rs @@ -1,6 +1,6 @@ use syn::{self, Ident, Fields}; -use overrides::Overrides; +use crate::overrides::Overrides; pub struct Variant { pub ident: Ident, diff --git a/src/fromsql.rs b/src/fromsql.rs index 9cd702e..dd403e5 100644 --- a/src/fromsql.rs +++ b/src/fromsql.rs @@ -3,10 +3,10 @@ use std::iter; use syn::{self, Ident, DeriveInput, Data, DataStruct, Fields, Lifetime}; use quote::Tokens; -use accepts; -use composites::Field; -use enums::Variant; -use overrides::Overrides; +use crate::accepts; +use crate::composites::Field; +use crate::enums::Variant; +use crate::overrides::Overrides; pub fn expand_derive_fromsql(input: DeriveInput) -> Result { let overrides = Overrides::extract(&input.attrs)?; diff --git a/src/lib.rs b/src/lib.rs index 202293b..b163f3e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,8 @@ #![recursion_limit = "256"] -extern crate proc_macro; -extern crate proc_macro2; -extern crate syn; #[macro_use] extern crate quote; +extern crate proc_macro; use proc_macro::TokenStream; diff --git a/src/tosql.rs b/src/tosql.rs index f45db02..b2ef4c7 100644 --- a/src/tosql.rs +++ b/src/tosql.rs @@ -2,10 +2,10 @@ use std::iter; use syn::{self, Ident, DeriveInput, Data, DataStruct, Fields}; use quote::Tokens; -use accepts; -use composites::Field; -use enums::Variant; -use overrides::Overrides; +use crate::accepts; +use crate::composites::Field; +use crate::enums::Variant; +use crate::overrides::Overrides; pub fn expand_derive_tosql(input: DeriveInput) -> Result { let overrides = Overrides::extract(&input.attrs)?;