Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4561d44

Browse files
committed
Add#[postgres(transparent)]
1 parent630f179 commit4561d44

File tree

10 files changed

+251
-46
lines changed

10 files changed

+251
-46
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use postgres_types::{FromSql,ToSql};
2+
3+
#[derive(ToSql,Debug)]
4+
#[postgres(transparent)]
5+
structToSqlTransparentStruct{
6+
a:i32
7+
}
8+
9+
#[derive(FromSql,Debug)]
10+
#[postgres(transparent)]
11+
structFromSqlTransparentStruct{
12+
a:i32
13+
}
14+
15+
#[derive(ToSql,Debug)]
16+
#[postgres(transparent)]
17+
enumToSqlTransparentEnum{
18+
Foo
19+
}
20+
21+
#[derive(FromSql,Debug)]
22+
#[postgres(transparent)]
23+
enumFromSqlTransparentEnum{
24+
Foo
25+
}
26+
27+
#[derive(ToSql,Debug)]
28+
#[postgres(transparent)]
29+
structToSqlTransparentTwoFieldTupleStruct(i32,i32);
30+
31+
#[derive(FromSql,Debug)]
32+
#[postgres(transparent)]
33+
structFromSqlTransparentTwoFieldTupleStruct(i32,i32);
34+
35+
fnmain(){}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
error: #[postgres(transparent)] may only be applied to single field tuple structs
2+
--> src/compile-fail/invalid-transparent.rs:4:1
3+
|
4+
4 | / #[postgres(transparent)]
5+
5 | | struct ToSqlTransparentStruct {
6+
6 | | a: i32
7+
7 | | }
8+
| |_^
9+
10+
error: #[postgres(transparent)] may only be applied to single field tuple structs
11+
--> src/compile-fail/invalid-transparent.rs:10:1
12+
|
13+
10 | / #[postgres(transparent)]
14+
11 | | struct FromSqlTransparentStruct {
15+
12 | | a: i32
16+
13 | | }
17+
| |_^
18+
19+
error: #[postgres(transparent)] may only be applied to single field tuple structs
20+
--> src/compile-fail/invalid-transparent.rs:16:1
21+
|
22+
16 | / #[postgres(transparent)]
23+
17 | | enum ToSqlTransparentEnum {
24+
18 | | Foo
25+
19 | | }
26+
| |_^
27+
28+
error: #[postgres(transparent)] may only be applied to single field tuple structs
29+
--> src/compile-fail/invalid-transparent.rs:22:1
30+
|
31+
22 | / #[postgres(transparent)]
32+
23 | | enum FromSqlTransparentEnum {
33+
24 | | Foo
34+
25 | | }
35+
| |_^
36+
37+
error: #[postgres(transparent)] may only be applied to single field tuple structs
38+
--> src/compile-fail/invalid-transparent.rs:28:1
39+
|
40+
28 | / #[postgres(transparent)]
41+
29 | | struct ToSqlTransparentTwoFieldTupleStruct(i32, i32);
42+
| |_____________________________________________________^
43+
44+
error: #[postgres(transparent)] may only be applied to single field tuple structs
45+
--> src/compile-fail/invalid-transparent.rs:32:1
46+
|
47+
32 | / #[postgres(transparent)]
48+
33 | | struct FromSqlTransparentTwoFieldTupleStruct(i32, i32);
49+
| |_______________________________________________________^

‎postgres-derive-test/src/lib.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::fmt;
77
mod composites;
88
mod domains;
99
mod enums;
10+
mod transparent;
1011

1112
pubfntest_type<T,S>(conn:&mutClient,sql_type:&str,checks:&[(T,S)])
1213
where
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
use postgres::{Client,NoTls};
2+
use postgres_types::{FromSql,ToSql};
3+
4+
#[test]
5+
fnround_trip(){
6+
#[derive(FromSql,ToSql,Debug,PartialEq)]
7+
#[postgres(transparent)]
8+
structUserId(i32);
9+
10+
assert_eq!(
11+
Client::connect("user=postgres host=localhost port=5433",NoTls)
12+
.unwrap()
13+
.query_one("SELECT $1::integer",&[&UserId(123)])
14+
.unwrap()
15+
.get::<_,UserId>(0),
16+
UserId(123)
17+
);
18+
}

‎postgres-derive/src/accepts.rs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ use syn::Ident;
66
usecrate::composites::Field;
77
usecrate::enums::Variant;
88

9+
pubfntransparent_body(field:&syn::Field) ->TokenStream{
10+
let ty =&field.ty;
11+
12+
quote!{
13+
<#tyas::postgres_types::ToSql>::accepts(type_)
14+
}
15+
}
16+
917
pubfndomain_body(name:&str,field:&syn::Field) ->TokenStream{
1018
let ty =&field.ty;
1119

‎postgres-derive/src/fromsql.rs‎

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,36 @@ use crate::overrides::Overrides;
1111
pubfnexpand_derive_fromsql(input:DeriveInput) ->Result<TokenStream,Error>{
1212
let overrides =Overrides::extract(&input.attrs)?;
1313

14+
if overrides.name.is_some() && overrides.transparent{
15+
returnErr(Error::new_spanned(
16+
&input,
17+
"#[postgres(transparent)] is not allowed with #[postgres(name =\"...\")]",
18+
));
19+
}
20+
1421
let name = overrides.name.unwrap_or_else(|| input.ident.to_string());
1522

16-
let(accepts_body, to_sql_body) =match input.data{
23+
let(accepts_body, to_sql_body) =if overrides.transparent{
24+
match input.data{
25+
Data::Struct(DataStruct{
26+
fields:Fields::Unnamed(ref fields),
27+
..
28+
})if fields.unnamed.len() ==1 =>{
29+
let field = fields.unnamed.first().unwrap();
30+
(
31+
accepts::transparent_body(field),
32+
transparent_body(&input.ident, field),
33+
)
34+
}
35+
_ =>{
36+
returnErr(Error::new_spanned(
37+
input,
38+
"#[postgres(transparent)] may only be applied to single field tuple structs",
39+
))
40+
}
41+
}
42+
}else{
43+
match input.data{
1744
Data::Enum(ref data) =>{
1845
let variants = data
1946
.variants
@@ -55,6 +82,7 @@ pub fn expand_derive_fromsql(input: DeriveInput) -> Result<TokenStream, Error> {
5582
"#[derive(FromSql)] may only be applied to structs, single field tuple structs, and enums",
5683
))
5784
}
85+
}
5886
};
5987

6088
let ident =&input.ident;
@@ -77,6 +105,13 @@ pub fn expand_derive_fromsql(input: DeriveInput) -> Result<TokenStream, Error> {
77105
Ok(out)
78106
}
79107

108+
fntransparent_body(ident:&Ident,field:&syn::Field) ->TokenStream{
109+
let ty =&field.ty;
110+
quote!{
111+
<#tyas postgres_types::FromSql>::from_sql(_type, buf).map(#ident)
112+
}
113+
}
114+
80115
fnenum_body(ident:&Ident,variants:&[Variant]) ->TokenStream{
81116
let variant_names = variants.iter().map(|v|&v.name);
82117
let idents = iter::repeat(ident);

‎postgres-derive/src/lib.rs‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
externcrate proc_macro;
55

66
use proc_macro::TokenStream;
7+
use syn::parse_macro_input;
78

89
mod accepts;
910
mod composites;
@@ -14,15 +15,17 @@ mod tosql;
1415

1516
#[proc_macro_derive(ToSql, attributes(postgres))]
1617
pubfnderive_tosql(input:TokenStream) ->TokenStream{
17-
let input = syn::parse(input).unwrap();
18+
let input =parse_macro_input!(input);
19+
1820
tosql::expand_derive_tosql(input)
1921
.unwrap_or_else(|e| e.to_compile_error())
2022
.into()
2123
}
2224

2325
#[proc_macro_derive(FromSql, attributes(postgres))]
2426
pubfnderive_fromsql(input:TokenStream) ->TokenStream{
25-
let input = syn::parse(input).unwrap();
27+
let input =parse_macro_input!(input);
28+
2629
fromsql::expand_derive_fromsql(input)
2730
.unwrap_or_else(|e| e.to_compile_error())
2831
.into()

‎postgres-derive/src/overrides.rs‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@ use syn::{Attribute, Error, Lit, Meta, NestedMeta};
22

33
pubstructOverrides{
44
pubname:Option<String>,
5+
pubtransparent:bool,
56
}
67

78
implOverrides{
89
pubfnextract(attrs:&[Attribute]) ->Result<Overrides,Error>{
9-
letmut overrides =Overrides{name:None};
10+
letmut overrides =Overrides{
11+
name:None,
12+
transparent:false,
13+
};
1014

1115
for attrin attrs{
12-
let attr =match attr.parse_meta(){
13-
Ok(meta) => meta,
14-
Err(_) =>continue,
15-
};
16+
let attr = attr.parse_meta()?;
1617

1718
if !attr.path().is_ident("postgres"){
1819
continue;
@@ -39,7 +40,14 @@ impl Overrides {
3940

4041
overrides.name =Some(value);
4142
}
42-
bad =>returnErr(Error::new_spanned(bad,"expected a name-value meta item")),
43+
NestedMeta::Meta(Meta::Path(ref path)) =>{
44+
if !path.is_ident("transparent"){
45+
returnErr(Error::new_spanned(path,"unknown override"));
46+
}
47+
48+
overrides.transparent =true;
49+
}
50+
bad =>returnErr(Error::new_spanned(bad,"unknown attribute")),
4351
}
4452
}
4553
}

‎postgres-derive/src/tosql.rs‎

Lines changed: 70 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -11,46 +11,73 @@ use crate::overrides::Overrides;
1111
pubfnexpand_derive_tosql(input:DeriveInput) ->Result<TokenStream,Error>{
1212
let overrides =Overrides::extract(&input.attrs)?;
1313

14+
if overrides.name.is_some() && overrides.transparent{
15+
returnErr(Error::new_spanned(
16+
&input,
17+
"#[postgres(transparent)] is not allowed with #[postgres(name =\"...\")]",
18+
));
19+
}
20+
1421
let name = overrides.name.unwrap_or_else(|| input.ident.to_string());
1522

16-
let(accepts_body, to_sql_body) =match input.data{
17-
Data::Enum(ref data) =>{
18-
let variants = data
19-
.variants
20-
.iter()
21-
.map(Variant::parse)
22-
.collect::<Result<Vec<_>,_>>()?;
23-
(
24-
accepts::enum_body(&name,&variants),
25-
enum_body(&input.ident,&variants),
26-
)
27-
}
28-
Data::Struct(DataStruct{
29-
fields:Fields::Unnamed(ref fields),
30-
..
31-
})if fields.unnamed.len() ==1 =>{
32-
let field = fields.unnamed.first().unwrap();
33-
(accepts::domain_body(&name, field),domain_body())
34-
}
35-
Data::Struct(DataStruct{
36-
fields:Fields::Named(ref fields),
37-
..
38-
}) =>{
39-
let fields = fields
40-
.named
41-
.iter()
42-
.map(Field::parse)
43-
.collect::<Result<Vec<_>,_>>()?;
44-
(
45-
accepts::composite_body(&name,"ToSql",&fields),
46-
composite_body(&fields),
47-
)
23+
let(accepts_body, to_sql_body) =if overrides.transparent{
24+
match input.data{
25+
Data::Struct(DataStruct{
26+
fields:Fields::Unnamed(ref fields),
27+
..
28+
})if fields.unnamed.len() ==1 =>{
29+
let field = fields.unnamed.first().unwrap();
30+
31+
(accepts::transparent_body(field),transparent_body())
32+
}
33+
_ =>{
34+
returnErr(Error::new_spanned(
35+
input,
36+
"#[postgres(transparent)] may only be applied to single field tuple structs",
37+
));
38+
}
4839
}
49-
_ =>{
50-
returnErr(Error::new_spanned(
51-
input,
52-
"#[derive(ToSql)] may only be applied to structs, single field tuple structs, and enums",
53-
));
40+
}else{
41+
match input.data{
42+
Data::Enum(ref data) =>{
43+
let variants = data
44+
.variants
45+
.iter()
46+
.map(Variant::parse)
47+
.collect::<Result<Vec<_>,_>>()?;
48+
(
49+
accepts::enum_body(&name,&variants),
50+
enum_body(&input.ident,&variants),
51+
)
52+
}
53+
Data::Struct(DataStruct{
54+
fields:Fields::Unnamed(ref fields),
55+
..
56+
})if fields.unnamed.len() ==1 =>{
57+
let field = fields.unnamed.first().unwrap();
58+
59+
(accepts::domain_body(&name, field),domain_body())
60+
}
61+
Data::Struct(DataStruct{
62+
fields:Fields::Named(ref fields),
63+
..
64+
}) =>{
65+
let fields = fields
66+
.named
67+
.iter()
68+
.map(Field::parse)
69+
.collect::<Result<Vec<_>,_>>()?;
70+
(
71+
accepts::composite_body(&name,"ToSql",&fields),
72+
composite_body(&fields),
73+
)
74+
}
75+
_ =>{
76+
returnErr(Error::new_spanned(
77+
input,
78+
"#[derive(ToSql)] may only be applied to structs, single field tuple structs, and enums",
79+
));
80+
}
5481
}
5582
};
5683

@@ -78,6 +105,12 @@ pub fn expand_derive_tosql(input: DeriveInput) -> Result<TokenStream, Error> {
78105
Ok(out)
79106
}
80107

108+
fntransparent_body() ->TokenStream{
109+
quote!{
110+
postgres_types::ToSql::to_sql(&self.0, _type, buf)
111+
}
112+
}
113+
81114
fnenum_body(ident:&Ident,variants:&[Variant]) ->TokenStream{
82115
let idents = iter::repeat(ident);
83116
let variant_idents = variants.iter().map(|v|&v.ident);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp