1- use std:: old_io:: ByRefReader ;
2- use std:: old_io:: util:: LimitReader ;
1+ use std:: io:: prelude:: * ;
2+ use postgres:: { self , Type , Kind , ToSql , FromSql } ;
3+ use postgres:: types:: IsNull ;
4+ use byteorder:: { ReadBytesExt , WriteBytesExt , BigEndian } ;
35
4- use time:: Timespec ;
5- use postgres:: Type ;
6- use postgres:: types:: { RawFromSql , RawToSql } ;
7-
8- use { postgres, Range , RangeBound , BoundType , BoundSided , Normalizable } ;
9-
10- macro_rules! check_types {
11- ( $actual: ident, $( $expected: pat) ,+) => (
12- match $actual {
13- $( & $expected) |+ => { }
14- actual => return Err ( :: postgres:: Error :: WrongType ( actual. clone( ) ) )
15- }
16- )
17- }
18-
19- macro_rules! from_sql_impl {
20- ( $t: ty, $( $oid: pat) ,+) => {
21- impl :: postgres:: FromSql for Option <:: Range <$t>> {
22- fn from_sql( ty: & :: postgres:: Type , raw: Option <& [ u8 ] >) -> :: postgres:: Result <Self > {
23- check_types!( ty, $( $oid) ,+) ;
24-
25- match raw {
26- Some ( mut raw) => :: postgres:: types:: RawFromSql :: raw_from_sql( ty, & mut raw) . map( Some ) ,
27- None => Ok ( None ) ,
28- }
29- }
30- }
31-
32- impl :: postgres:: FromSql for :: Range <$t> {
33- fn from_sql( ty: & :: postgres:: Type , raw: Option <& [ u8 ] >) -> :: postgres:: Result <Self > {
34- let v: :: postgres:: Result <Option <Self >> = :: postgres:: FromSql :: from_sql( ty, raw) ;
35- match v {
36- Ok ( None ) => Err ( :: postgres:: Error :: WasNull ) ,
37- Ok ( Some ( v) ) => Ok ( v) ,
38- Err ( err) => Err ( err) ,
39- }
40- }
41- }
42- }
43- }
44-
45- macro_rules! to_sql_impl {
46- ( $t: ty, $( $oid: pat) ,+) => {
47- impl :: postgres:: ToSql for :: Range <$t> {
48- fn to_sql( & self , ty: & :: postgres:: Type ) -> :: postgres:: Result <Option <Vec <u8 >>> {
49- check_types!( ty, $( $oid) ,+) ;
50-
51- let mut writer = vec![ ] ;
52- try!( self . raw_to_sql( ty, & mut writer) ) ;
53- Ok ( Some ( writer) )
54- }
55- }
56-
57- impl :: postgres:: ToSql for Option <:: Range <$t>> {
58- fn to_sql( & self , ty: & :: postgres:: Type ) -> :: postgres:: Result <Option <Vec <u8 >>> {
59- check_types!( ty, $( $oid) ,+) ;
60- match * self {
61- Some ( ref arr) => arr. to_sql( ty) ,
62- None => Ok ( None )
63- }
64- }
65- }
66- }
67- }
6+ use { Range , RangeBound , BoundType , BoundSided , Normalizable } ;
687
698const RANGE_UPPER_UNBOUNDED : i8 = 0b0001_0000 ;
709const RANGE_LOWER_UNBOUNDED : i8 = 0b0000_1000 ;
7110const RANGE_UPPER_INCLUSIVE : i8 = 0b0000_0100 ;
7211const RANGE_LOWER_INCLUSIVE : i8 = 0b0000_0010 ;
7312const RANGE_EMPTY : i8 = 0b0000_0001 ;
7413
75- impl < T > RawFromSql for Range < T > where T : PartialOrd +Normalizable +RawFromSql {
76- fn raw_from_sql < R : Reader > ( ty : & Type , rdr : & mut R ) -> postgres:: Result < Range < T > > {
14+ impl < T > FromSql for Range < T > where T : PartialOrd +Normalizable +FromSql {
15+ fn from_sql < R : Read > ( ty : & Type , rdr : & mut R ) -> postgres:: Result < Range < T > > {
16+ let element_type = match ty. kind ( ) {
17+ & Kind :: Range ( ref ty) => ty,
18+ _ => panic ! ( "unexpected type {:?}" , ty)
19+ } ;
20+
7721 let t = try!( rdr. read_i8 ( ) ) ;
7822
7923 if t & RANGE_EMPTY != 0 {
@@ -82,38 +26,45 @@ impl<T> RawFromSql for Range<T> where T: PartialOrd+Normalizable+RawFromSql {
8226
8327 fn make_bound < S , T , R > ( ty : & Type , rdr : & mut R , tag : i8 , bound_flag : i8 , inclusive_flag : i8 )
8428 -> postgres:: Result < Option < RangeBound < S , T > > >
85- where S : BoundSided , T : PartialOrd +Normalizable +RawFromSql , R : Reader {
29+ where S : BoundSided , T : PartialOrd +Normalizable +FromSql , R : Read {
8630 match tag & bound_flag {
8731 0 => {
8832 let type_ = match tag & inclusive_flag {
8933 0 => BoundType :: Exclusive ,
9034 _ => BoundType :: Inclusive ,
9135 } ;
92- let len = try!( rdr. read_be_i32 ( ) ) as usize ;
93- let mut limit = LimitReader :: new ( rdr. by_ref ( ) , len) ;
94- let bound = try!( RawFromSql :: raw_from_sql ( ty, & mut limit) ) ;
36+ let len = try!( rdr. read_i32 :: < BigEndian > ( ) ) as u64 ;
37+ let mut limit = rdr. take ( len) ;
38+ let bound = try!( FromSql :: from_sql ( ty, & mut limit) ) ;
9539 if limit. limit ( ) != 0 {
96- return Err ( postgres:: Error :: BadData ) ;
40+ return Err ( postgres:: Error :: BadResponse ) ;
9741 }
9842 Ok ( Some ( RangeBound :: new ( bound, type_) ) )
9943 }
10044 _ => Ok ( None )
10145 }
10246 }
10347
104- let element_type = ty. element_type ( ) . unwrap ( ) ;
105- let lower = try!( make_bound ( & element_type, rdr, t, RANGE_LOWER_UNBOUNDED , RANGE_LOWER_INCLUSIVE ) ) ;
106- let upper = try!( make_bound ( & element_type, rdr, t, RANGE_UPPER_UNBOUNDED , RANGE_UPPER_INCLUSIVE ) ) ;
48+ let lower = try!( make_bound ( element_type, rdr, t, RANGE_LOWER_UNBOUNDED , RANGE_LOWER_INCLUSIVE ) ) ;
49+ let upper = try!( make_bound ( element_type, rdr, t, RANGE_UPPER_UNBOUNDED , RANGE_UPPER_INCLUSIVE ) ) ;
10750 Ok ( Range :: new ( lower, upper) )
10851 }
52+
53+ fn accepts ( ty : & Type ) -> bool {
54+ match ty. kind ( ) {
55+ & Kind :: Range ( ref inner) => <T as FromSql >:: accepts ( inner) ,
56+ _ => false ,
57+ }
58+ }
10959}
11060
111- from_sql_impl ! ( i32 , Type :: Int4Range ) ;
112- from_sql_impl ! ( i64 , Type :: Int8Range ) ;
113- from_sql_impl ! ( Timespec , Type :: TsRange , Type :: TstzRange ) ;
61+ impl < T > ToSql for Range < T > where T : PartialOrd +Normalizable +ToSql {
62+ fn to_sql < W : ?Sized +Write > ( & self , ty : & Type , mut buf : & mut W ) -> postgres:: Result < IsNull > {
63+ let element_type = match ty. kind ( ) {
64+ & Kind :: Range ( ref ty) => ty,
65+ _ => panic ! ( "unexpected type {:?}" , ty)
66+ } ;
11467
115- impl < T > RawToSql for Range < T > where T : PartialOrd +Normalizable +RawToSql {
116- fn raw_to_sql < W : Writer > ( & self , ty : & Type , buf : & mut W ) -> postgres:: Result < ( ) > {
11768 let mut tag = 0 ;
11869 if self . is_empty ( ) {
11970 tag |= RANGE_EMPTY ;
@@ -132,28 +83,32 @@ impl<T> RawToSql for Range<T> where T: PartialOrd+Normalizable+RawToSql {
13283
13384 try!( buf. write_i8 ( tag) ) ;
13485
135- fn write_value < S , T , W > ( ty : & Type , buf : & mut W , v : Option < & RangeBound < S , T > > ) -> postgres:: Result < ( ) >
136- where S : BoundSided , T : RawToSql , W : Writer {
86+ fn write_value < S , T , W : ? Sized > ( ty : & Type , mut buf : & mut W , v : Option < & RangeBound < S , T > > ) -> postgres:: Result < ( ) >
87+ where S : BoundSided , T : ToSql , W : Write {
13788 if let Some ( bound) = v {
13889 let mut inner_buf = vec ! [ ] ;
139- try!( bound. value . raw_to_sql ( ty, & mut inner_buf) ) ;
140- try!( buf. write_be_u32 ( inner_buf. len ( ) as u32 ) ) ;
90+ try!( bound. value . to_sql ( ty, & mut inner_buf) ) ;
91+ try!( buf. write_u32 :: < BigEndian > ( inner_buf. len ( ) as u32 ) ) ;
14192 try!( buf. write_all ( & * inner_buf) ) ;
14293 }
14394 Ok ( ( ) )
14495 }
14596
146- let element_type = ty. element_type ( ) . unwrap ( ) ;
14797 try!( write_value ( & element_type, buf, self . lower ( ) ) ) ;
14898 try!( write_value ( & element_type, buf, self . upper ( ) ) ) ;
14999
150- Ok ( ( ) )
100+ Ok ( IsNull :: No )
151101 }
152- }
153102
154- to_sql_impl ! ( i32 , Type :: Int4Range ) ;
155- to_sql_impl ! ( i64 , Type :: Int8Range ) ;
156- to_sql_impl ! ( Timespec , Type :: TsRange , Type :: TstzRange ) ;
103+ fn accepts ( ty : & Type ) -> bool {
104+ match ty. kind ( ) {
105+ & Kind :: Range ( ref inner) => <T as ToSql >:: accepts ( inner) ,
106+ _ => false ,
107+ }
108+ }
109+
110+ to_sql_checked ! ( ) ;
111+ }
157112
158113#[ cfg( test) ]
159114mod test {
@@ -187,11 +142,11 @@ mod test {
187142 let conn = Connection :: connect ( "postgres://postgres@localhost" , & SslMode :: None ) . unwrap ( ) ;
188143 for & ( ref val, ref repr) in checks {
189144 let stmt = conn. prepare ( & * format ! ( "SELECT {}::{}" , * repr, sql_type) ) . unwrap ( ) ;
190- let result = stmt. query ( & [ ] ) . unwrap ( ) . next ( ) . unwrap ( ) . get ( 0 ) ;
145+ let result = stmt. query ( & [ ] ) . unwrap ( ) . iter ( ) . next ( ) . unwrap ( ) . get ( 0 ) ;
191146 assert ! ( val == & result) ;
192147
193148 let stmt = conn. prepare ( & * format ! ( "SELECT $1::{}" , sql_type) ) . unwrap ( ) ;
194- let result = stmt. query ( & [ val] ) . unwrap ( ) . next ( ) . unwrap ( ) . get ( 0 ) ;
149+ let result = stmt. query ( & [ val] ) . unwrap ( ) . iter ( ) . next ( ) . unwrap ( ) . get ( 0 ) ;
195150 assert ! ( val == & result) ;
196151 }
197152 }
0 commit comments