@@ -26,45 +26,97 @@ impl Encode<'_, Mssql> for i8 {
2626 }
2727}
2828
29- fn decode_int_direct < T , const N : usize > (
30- value : MssqlValueRef < ' _ > ,
31- from_le_bytes : impl FnOnce ( [ u8 ; N ] ) -> T ,
29+ fn decode_int_bytes < T , U , const N : usize > (
30+ bytes : & [ u8 ] ,
31+ type_info : & MssqlTypeInfo ,
32+ from_le_bytes : impl Fn ( [ u8 ; N ] ) -> U ,
3233) -> Result < T , BoxDynError >
3334where
34- T : TryFrom < i64 > ,
35+ T : TryFrom < U > ,
36+ T :: Error : std:: error:: Error + Send + Sync + ' static ,
37+ U : std:: fmt:: Display + Copy ,
38+ {
39+ if bytes. len ( ) != N {
40+ return Err ( err_protocol ! (
41+ "{} should have exactly {} byte(s), got {}" ,
42+ type_info,
43+ N ,
44+ bytes. len( )
45+ )
46+ . into ( ) ) ;
47+ }
48+
49+ let mut buf = [ 0u8 ; N ] ;
50+ buf. copy_from_slice ( bytes) ;
51+ let val = from_le_bytes ( buf) ;
52+
53+ T :: try_from ( val) . map_err ( |err| {
54+ err_protocol ! (
55+ "Converting {} {} to {} failed: {}" ,
56+ type_info,
57+ val,
58+ type_name:: <T >( ) ,
59+ err
60+ )
61+ . into ( )
62+ } )
63+ }
64+
65+ fn decode_tinyint < T > ( bytes : & [ u8 ] , type_info : & MssqlTypeInfo ) -> Result < T , BoxDynError >
66+ where
67+ T : TryFrom < u8 > ,
3568 T :: Error : std:: error:: Error + Send + Sync + ' static ,
3669{
37- let ty = value. type_info . 0 . ty ;
38- let precision = value. type_info . 0 . precision ;
39- let scale = value. type_info . 0 . scale ;
70+ if bytes. len ( ) != 1 {
71+ return Err ( err_protocol ! (
72+ "{} should have exactly 1 byte, got {}" ,
73+ type_info,
74+ bytes. len( )
75+ )
76+ . into ( ) ) ;
77+ }
78+
79+ let val = u8:: from_le_bytes ( [ bytes[ 0 ] ] ) ;
80+ T :: try_from ( val) . map_err ( |err| {
81+ err_protocol ! (
82+ "Converting {} {} to {} failed: {}" ,
83+ type_info,
84+ val,
85+ type_name:: <T >( ) ,
86+ err
87+ )
88+ . into ( )
89+ } )
90+ }
91+
92+ fn decode_int_direct < T > ( value : MssqlValueRef < ' _ > ) -> Result < T , BoxDynError >
93+ where
94+ T : TryFrom < i64 > + TryFrom < u8 > + TryFrom < i16 > + TryFrom < i32 > ,
95+ <T as TryFrom < i64 > >:: Error : std:: error:: Error + Send + Sync + ' static ,
96+ <T as TryFrom < u8 > >:: Error : std:: error:: Error + Send + Sync + ' static ,
97+ <T as TryFrom < i16 > >:: Error : std:: error:: Error + Send + Sync + ' static ,
98+ <T as TryFrom < i32 > >:: Error : std:: error:: Error + Send + Sync + ' static ,
99+ {
100+ let type_info = & value. type_info ;
101+ let ty = type_info. 0 . ty ;
102+ let precision = type_info. 0 . precision ;
103+ let scale = type_info. 0 . scale ;
104+ let bytes_val = value. as_bytes ( ) ?;
40105
41106 match ty {
42- DataType :: SmallInt
43- | DataType :: Int
44- | DataType :: TinyInt
45- | DataType :: BigInt
46- | DataType :: IntN => {
47- let bytes_val = value. as_bytes ( ) ?;
48- let len = bytes_val. len ( ) ;
49-
50- if len > N {
51- return Err ( err_protocol ! (
52- "Decoding {:?} as {} failed because type {:?} has {} bytes, but can only handle {} bytes" ,
53- value,
54- type_name:: <T >( ) ,
55- ty,
56- len,
57- N
58- )
59- . into ( ) ) ;
60- }
61-
62- let mut buf = [ 0u8 ; N ] ;
63- buf[ ..len] . copy_from_slice ( bytes_val) ;
64- Ok ( from_le_bytes ( buf) )
65- }
107+ DataType :: TinyInt => decode_tinyint ( bytes_val, type_info) ,
108+ DataType :: SmallInt => decode_int_bytes ( bytes_val, type_info, i16:: from_le_bytes) ,
109+ DataType :: Int => decode_int_bytes ( bytes_val, type_info, i32:: from_le_bytes) ,
110+ DataType :: BigInt => decode_int_bytes ( bytes_val, type_info, i64:: from_le_bytes) ,
111+ DataType :: IntN => match bytes_val. len ( ) {
112+ 1 => decode_tinyint ( bytes_val, type_info) ,
113+ 2 => decode_int_bytes ( bytes_val, type_info, i16:: from_le_bytes) ,
114+ 4 => decode_int_bytes ( bytes_val, type_info, i32:: from_le_bytes) ,
115+ 8 => decode_int_bytes ( bytes_val, type_info, i64:: from_le_bytes) ,
116+ len => Err ( err_protocol ! ( "IntN with {} bytes is not supported" , len) . into ( ) ) ,
117+ } ,
66118 DataType :: Numeric | DataType :: NumericN | DataType :: Decimal | DataType :: DecimalN => {
67- let i64_val = decode_numeric ( value . as_bytes ( ) ? , precision, scale) ?;
119+ let i64_val = decode_numeric ( bytes_val , precision, scale) ?;
68120 convert_integer :: < T > ( i64_val)
69121 }
70122 _ => Err ( err_protocol ! (
79131
80132impl Decode < ' _ , Mssql > for i8 {
81133 fn decode ( value : MssqlValueRef < ' _ > ) -> Result < Self , BoxDynError > {
82- decode_int_direct ( value, i8 :: from_le_bytes )
134+ decode_int_direct ( value)
83135 }
84136}
85137
@@ -106,7 +158,7 @@ impl Encode<'_, Mssql> for i16 {
106158
107159impl Decode < ' _ , Mssql > for i16 {
108160 fn decode ( value : MssqlValueRef < ' _ > ) -> Result < Self , BoxDynError > {
109- decode_int_direct ( value, i16 :: from_le_bytes )
161+ decode_int_direct ( value)
110162 }
111163}
112164
@@ -130,7 +182,7 @@ impl Encode<'_, Mssql> for i32 {
130182
131183impl Decode < ' _ , Mssql > for i32 {
132184 fn decode ( value : MssqlValueRef < ' _ > ) -> Result < Self , BoxDynError > {
133- decode_int_direct ( value, i32 :: from_le_bytes )
185+ decode_int_direct ( value)
134186 }
135187}
136188
@@ -165,7 +217,7 @@ impl Encode<'_, Mssql> for i64 {
165217
166218impl Decode < ' _ , Mssql > for i64 {
167219 fn decode ( value : MssqlValueRef < ' _ > ) -> Result < Self , BoxDynError > {
168- decode_int_direct ( value, i64 :: from_le_bytes )
220+ decode_int_direct ( value)
169221 }
170222}
171223
0 commit comments