11use std:: rt:: io:: Decorator ;
2- use std:: rt:: io:: extensions:: WriterByteConversions ;
3- use std:: rt:: io:: mem:: MemWriter ;
2+ use std:: rt:: io:: extensions:: { WriterByteConversions , ReaderByteConversions } ;
3+ use std:: rt:: io:: mem:: { MemWriter , MemReader } ;
44use std:: str;
5- use std:: f32;
6- use std:: f64;
75
86pub type Oid = i32 ;
97
108// Values from pg_type.h
119static BOOLOID : Oid = 16 ;
10+ static BYTEAOID : Oid = 17 ;
1211static INT8OID : Oid = 20 ;
1312static INT2OID : Oid = 21 ;
1413static INT4OID : Oid = 23 ;
@@ -21,20 +20,40 @@ pub enum Format {
2120 Binary = 1
2221}
2322
23+ pub fn result_format ( ty : Oid ) -> Format {
24+ match ty {
25+ BOOLOID |
26+ BYTEAOID |
27+ INT8OID |
28+ INT2OID |
29+ INT4OID |
30+ FLOAT4OID |
31+ FLOAT8OID => Binary ,
32+ _ => Text
33+ }
34+ }
35+
36+ macro_rules! check_oid(
37+ ( $expected: ident, $actual: ident) => (
38+ if $expected != $actual {
39+ fail!( "Expected Oid %? but got Oid %?" , $expected, $actual) ;
40+ }
41+ )
42+ )
43+
2444pub trait FromSql {
25- fn from_sql ( raw : & Option < ~[ u8 ] > ) -> Self ;
45+ fn from_sql ( ty : Oid , raw : & Option < ~[ u8 ] > ) -> Self ;
2646}
2747
28- macro_rules! from_str_impl (
29- ( $t: ty) => (
48+ macro_rules! from_conversions_impl (
49+ ( $oid : ident , $ t: ty, $f : ident ) => (
3050 impl FromSql for Option <$t> {
31- fn from_sql( raw: & Option <~[ u8 ] >) -> Option <$t> {
32- match * raw {
33- None => None ,
34- Some ( ref buf) => {
35- let s = str :: from_bytes_slice( buf. as_slice( ) ) ;
36- Some ( FromStr :: from_str( s) . unwrap( ) )
37- }
51+ fn from_sql( ty: Oid , raw: & Option <~[ u8 ] >) -> Option <$t> {
52+ check_oid!( $oid, ty)
53+ do raw. map |buf| {
54+ // TODO change to BufReader when implemented
55+ let mut reader = MemReader :: new( buf. to_owned( ) ) ;
56+ reader. $f( )
3857 }
3958 }
4059 }
@@ -44,109 +63,58 @@ macro_rules! from_str_impl(
4463macro_rules! from_option_impl(
4564 ( $t: ty) => (
4665 impl FromSql for $t {
47- fn from_sql( raw: & Option <~[ u8 ] >) -> $t {
66+ fn from_sql( ty : Oid , raw: & Option <~[ u8 ] >) -> $t {
4867 // FIXME when you can specify Self types properly
49- let ret: Option <$t> = FromSql :: from_sql( raw) ;
68+ let ret: Option <$t> = FromSql :: from_sql( ty , raw) ;
5069 ret. unwrap( )
5170 }
5271 }
5372 )
5473)
5574
5675impl FromSql for Option < bool > {
57- fn from_sql ( raw : & Option < ~[ u8 ] > ) -> Option < bool > {
58- match * raw {
59- None => None ,
60- Some ( ref buf) => {
61- assert_eq ! ( 1 , buf. len( ) ) ;
62- match buf[ 0 ] as char {
63- 't' => Some ( true ) ,
64- 'f' => Some ( false ) ,
65- byte => fail ! ( "Invalid byte: %?" , byte)
66- }
67- }
76+ fn from_sql ( ty : Oid , raw : & Option < ~[ u8 ] > ) -> Option < bool > {
77+ check_oid ! ( BOOLOID , ty)
78+ do raw. map |buf| {
79+ buf[ 0 ] != 0
6880 }
6981 }
7082}
7183from_option_impl ! ( bool )
7284
73- from_str_impl ! ( int)
74- from_option_impl ! ( int)
75- from_str_impl ! ( i8 )
76- from_option_impl ! ( i8 )
77- from_str_impl ! ( i16 )
85+ from_conversions_impl ! ( INT2OID , i16 , read_be_i16_)
7886from_option_impl ! ( i16 )
79- from_str_impl ! ( i32 )
87+ from_conversions_impl ! ( INT4OID , i32 , read_be_i32_ )
8088from_option_impl ! ( i32 )
81- from_str_impl ! ( i64 )
89+ from_conversions_impl ! ( INT8OID , i64 , read_be_i64_ )
8290from_option_impl ! ( i64 )
83- from_str_impl ! ( uint)
84- from_option_impl ! ( uint)
85- from_str_impl ! ( u8 )
86- from_option_impl ! ( u8 )
87- from_str_impl ! ( u16 )
88- from_option_impl ! ( u16 )
89- from_str_impl ! ( u32 )
90- from_option_impl ! ( u32 )
91- from_str_impl ! ( u64 )
92- from_option_impl ! ( u64 )
93-
94- impl FromSql for Option < f32 > {
95- fn from_sql ( raw : & Option < ~[ u8 ] > ) -> Option < f32 > {
96- match * raw {
97- None => None ,
98- Some ( ref buf) => {
99- Some ( match str:: from_bytes_slice ( buf. as_slice ( ) ) {
100- "NaN" => f32:: NaN ,
101- "Infinity" => f32:: infinity,
102- "-Infinity" => f32:: neg_infinity,
103- str => FromStr :: from_str ( str) . unwrap ( )
104- } )
105- }
106- }
107- }
108- }
91+ from_conversions_impl ! ( FLOAT4OID , f32 , read_be_f32_)
10992from_option_impl ! ( f32 )
110-
111- impl FromSql for Option < f64 > {
112- fn from_sql ( raw : & Option < ~[ u8 ] > ) -> Option < f64 > {
113- match * raw {
114- None => None ,
115- Some ( ref buf) => {
116- Some ( match str:: from_bytes_slice ( buf. as_slice ( ) ) {
117- "NaN" => f64:: NaN ,
118- "Infinity" => f64:: infinity,
119- "-Infinity" => f64:: neg_infinity,
120- str => FromStr :: from_str ( str) . unwrap ( )
121- } )
122- }
123- }
124- }
125- }
93+ from_conversions_impl ! ( FLOAT8OID , f64 , read_be_f64_)
12694from_option_impl ! ( f64 )
12795
12896impl FromSql for Option < ~str > {
129- fn from_sql ( raw : & Option < ~[ u8 ] > ) -> Option < ~str > {
97+ fn from_sql ( ty : Oid , raw : & Option < ~[ u8 ] > ) -> Option < ~str > {
98+ check_oid ! ( VARCHAROID , ty)
13099 do raw. chain_ref |buf| {
131100 Some ( str:: from_bytes ( buf. as_slice ( ) ) )
132101 }
133102 }
134103}
135104from_option_impl ! ( ~str )
136105
106+ impl FromSql for Option < ~[ u8 ] > {
107+ fn from_sql ( ty : Oid , raw : & Option < ~[ u8 ] > ) -> Option < ~[ u8 ] > {
108+ check_oid ! ( BYTEAOID , ty)
109+ raw. clone ( )
110+ }
111+ }
112+ from_option_impl ! ( ~[ u8 ] )
113+
137114pub trait ToSql {
138115 fn to_sql ( & self , ty : Oid ) -> ( Format , Option < ~[ u8 ] > ) ;
139116}
140117
141- macro_rules! check_oid(
142- ( $expected: ident, $actual: ident) => (
143- if $expected != $actual {
144- fail!( "Attempted to bind an invalid type. Expected Oid %? but got \
145- Oid %?", $expected, $actual) ;
146- }
147- )
148- )
149-
150118macro_rules! to_option_impl(
151119 ( $oid: ident, $t: ty) => (
152120 impl ToSql for Option <$t> {
@@ -213,3 +181,22 @@ impl<'self> ToSql for Option<&'self str> {
213181 }
214182 }
215183}
184+
185+ impl < ' self > ToSql for & ' self [ u8 ] {
186+ fn to_sql ( & self , ty : Oid ) -> ( Format , Option < ~[ u8 ] > ) {
187+ check_oid ! ( BYTEAOID , ty)
188+ ( Binary , Some ( self . to_owned ( ) ) )
189+ }
190+ }
191+
192+ to_option_impl ! ( BYTEAOID , ~[ u8 ] )
193+
194+ impl < ' self > ToSql for Option < & ' self [ u8 ] > {
195+ fn to_sql ( & self , ty : Oid ) -> ( Format , Option < ~[ u8 ] > ) {
196+ check_oid ! ( BYTEAOID , ty)
197+ match * self {
198+ None => ( Text , None ) ,
199+ Some ( val) => val. to_sql ( ty)
200+ }
201+ }
202+ }
0 commit comments