11use  std:: any:: type_name; 
22use  std:: convert:: TryFrom ; 
3- use  std:: i16; 
43
54use  crate :: decode:: Decode ; 
65use  crate :: encode:: { Encode ,  IsNull } ; 
@@ -27,10 +26,85 @@ impl Encode<'_, Mssql> for i8 {
2726    } 
2827} 
2928
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 , 
33+ )  -> Result < T ,  BoxDynError > 
34+ where 
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_int_direct < T > ( value :  MssqlValueRef < ' _ > )  -> Result < T ,  BoxDynError > 
66+ where 
67+     T :  TryFrom < i64 >  + TryFrom < u8 >  + TryFrom < i16 >  + TryFrom < i32 > , 
68+     <T  as  TryFrom < i64 > >:: Error :  std:: error:: Error  + Send  + Sync  + ' static , 
69+     <T  as  TryFrom < u8 > >:: Error :  std:: error:: Error  + Send  + Sync  + ' static , 
70+     <T  as  TryFrom < i16 > >:: Error :  std:: error:: Error  + Send  + Sync  + ' static , 
71+     <T  as  TryFrom < i32 > >:: Error :  std:: error:: Error  + Send  + Sync  + ' static , 
72+ { 
73+     let  type_info = & value. type_info ; 
74+     let  ty = type_info. 0 . ty ; 
75+     let  precision = type_info. 0 . precision ; 
76+     let  scale = type_info. 0 . scale ; 
77+     let  bytes_val = value. as_bytes ( ) ?; 
78+ 
79+     match  ty { 
80+         DataType :: TinyInt  => decode_int_bytes ( bytes_val,  type_info,  u8:: from_le_bytes) , 
81+         DataType :: SmallInt  => decode_int_bytes ( bytes_val,  type_info,  i16:: from_le_bytes) , 
82+         DataType :: Int  => decode_int_bytes ( bytes_val,  type_info,  i32:: from_le_bytes) , 
83+         DataType :: BigInt  => decode_int_bytes ( bytes_val,  type_info,  i64:: from_le_bytes) , 
84+         DataType :: IntN  => match  bytes_val. len ( )  { 
85+             1  => decode_int_bytes ( bytes_val,  type_info,  u8:: from_le_bytes) , 
86+             2  => decode_int_bytes ( bytes_val,  type_info,  i16:: from_le_bytes) , 
87+             4  => decode_int_bytes ( bytes_val,  type_info,  i32:: from_le_bytes) , 
88+             8  => decode_int_bytes ( bytes_val,  type_info,  i64:: from_le_bytes) , 
89+             len => Err ( err_protocol ! ( "IntN with {} bytes is not supported" ,  len) . into ( ) ) , 
90+         } , 
91+         DataType :: Numeric  | DataType :: NumericN  | DataType :: Decimal  | DataType :: DecimalN  => { 
92+             let  i64_val = decode_numeric ( bytes_val,  precision,  scale) ?; 
93+             convert_integer :: < T > ( i64_val) 
94+         } 
95+         _ => Err ( err_protocol ! ( 
96+             "Decoding {:?} as {} failed because type {:?} is not supported" , 
97+             value, 
98+             type_name:: <T >( ) , 
99+             ty
100+         ) 
101+         . into ( ) ) , 
102+     } 
103+ } 
104+ 
30105impl  Decode < ' _ ,  Mssql >  for  i8  { 
31106    fn  decode ( value :  MssqlValueRef < ' _ > )  -> Result < Self ,  BoxDynError >  { 
32-         let  i64_val = <i64  as  Decode < Mssql > >:: decode ( value) ?; 
33-         convert_integer :: < Self > ( i64_val) 
107+         decode_int_direct ( value) 
34108    } 
35109} 
36110
@@ -57,8 +131,7 @@ impl Encode<'_, Mssql> for i16 {
57131
58132impl  Decode < ' _ ,  Mssql >  for  i16  { 
59133    fn  decode ( value :  MssqlValueRef < ' _ > )  -> Result < Self ,  BoxDynError >  { 
60-         let  i64_val = <i64  as  Decode < Mssql > >:: decode ( value) ?; 
61-         convert_integer :: < Self > ( i64_val) 
134+         decode_int_direct ( value) 
62135    } 
63136} 
64137
@@ -82,8 +155,7 @@ impl Encode<'_, Mssql> for i32 {
82155
83156impl  Decode < ' _ ,  Mssql >  for  i32  { 
84157    fn  decode ( value :  MssqlValueRef < ' _ > )  -> Result < Self ,  BoxDynError >  { 
85-         let  i64_val = <i64  as  Decode < Mssql > >:: decode ( value) ?; 
86-         convert_integer :: < Self > ( i64_val) 
158+         decode_int_direct ( value) 
87159    } 
88160} 
89161
@@ -118,43 +190,7 @@ impl Encode<'_, Mssql> for i64 {
118190
119191impl  Decode < ' _ ,  Mssql >  for  i64  { 
120192    fn  decode ( value :  MssqlValueRef < ' _ > )  -> Result < Self ,  BoxDynError >  { 
121-         let  ty = value. type_info . 0 . ty ; 
122-         let  precision = value. type_info . 0 . precision ; 
123-         let  scale = value. type_info . 0 . scale ; 
124- 
125-         match  ty { 
126-             DataType :: SmallInt 
127-             | DataType :: Int 
128-             | DataType :: TinyInt 
129-             | DataType :: BigInt 
130-             | DataType :: IntN  => { 
131-                 let  mut  buf = [ 0u8 ;  8 ] ; 
132-                 let  bytes_val = value. as_bytes ( ) ?; 
133-                 let  len = bytes_val. len ( ) ; 
134- 
135-                 if  len > buf. len ( )  { 
136-                     return  Err ( err_protocol ! ( 
137-                         "Decoding {:?} as a i64 failed because type {:?} has more than {} bytes" , 
138-                         value, 
139-                         ty, 
140-                         buf. len( ) 
141-                     ) 
142-                     . into ( ) ) ; 
143-                 } 
144- 
145-                 buf[ ..len] . copy_from_slice ( bytes_val) ; 
146-                 Ok ( i64:: from_le_bytes ( buf) ) 
147-             } 
148-             DataType :: Numeric  | DataType :: NumericN  | DataType :: Decimal  | DataType :: DecimalN  => { 
149-                 decode_numeric ( value. as_bytes ( ) ?,  precision,  scale) 
150-             } 
151-             _ => Err ( err_protocol ! ( 
152-                 "Decoding {:?} as a i64 failed because type {:?} is not implemented" , 
153-                 value, 
154-                 ty
155-             ) 
156-             . into ( ) ) , 
157-         } 
193+         decode_int_direct ( value) 
158194    } 
159195} 
160196
@@ -164,9 +200,12 @@ fn decode_numeric(bytes: &[u8], _precision: u8, mut scale: u8) -> Result<i64, Bo
164200    let  mut  fixed_bytes = [ 0u8 ;  16 ] ; 
165201    fixed_bytes[ 0 ..rest. len ( ) ] . copy_from_slice ( rest) ; 
166202    let  mut  numerator = u128:: from_le_bytes ( fixed_bytes) ; 
167-     while  scale > 0  { 
168-         scale -= 1 ; 
203+     while  numerator % 10  == 0  && scale > 0  { 
169204        numerator /= 10 ; 
205+         scale -= 1 ; 
206+     } 
207+     if  scale > 0  { 
208+         numerator /= 10u128 . pow ( scale as  u32 ) ; 
170209    } 
171210    let  n = i64:: try_from ( numerator) ?; 
172211    Ok ( n *  if  negative {  -1  }  else  {  1  } ) 
0 commit comments