11//! Conversions to and from Postgres's binary format for various types.
2- use byteorder:: { ReadBytesExt , WriteBytesExt , BigEndian } ;
2+ use byteorder:: { BigEndian , ByteOrder , ReadBytesExt , WriteBytesExt } ;
33use fallible_iterator:: FallibleIterator ;
4+ use std:: boxed:: Box as StdBox ;
45use std:: error:: Error ;
56use std:: str;
6- use std:: boxed:: Box as StdBox ;
77
8- use { Oid , IsNull , write_nullable , FromUsize } ;
8+ use { write_nullable , FromUsize , IsNull , Oid } ;
99
1010const RANGE_UPPER_UNBOUNDED : u8 = 0b0001_0000 ;
1111const RANGE_LOWER_UNBOUNDED : u8 = 0b0000_1000 ;
@@ -189,9 +189,7 @@ where
189189 }
190190
191191 let count = i32:: from_usize ( count) ?;
192- ( & mut buf[ base..base + 4 ] )
193- . write_i32 :: < BigEndian > ( count)
194- . unwrap ( ) ;
192+ BigEndian :: write_i32 ( & mut buf[ base..] , count) ;
195193
196194 Ok ( ( ) )
197195}
@@ -424,7 +422,6 @@ pub fn uuid_from_sql(buf: &[u8]) -> Result<[u8; 16], StdBox<Error + Sync + Send>
424422#[ inline]
425423pub fn array_to_sql < T , I , J , F > (
426424 dimensions : I ,
427- has_nulls : bool ,
428425 element_type : Oid ,
429426 elements : J ,
430427 mut serializer : F ,
@@ -437,7 +434,8 @@ where
437434{
438435 let dimensions_idx = buf. len ( ) ;
439436 buf. extend_from_slice ( & [ 0 ; 4 ] ) ;
440- buf. write_i32 :: < BigEndian > ( has_nulls as i32 ) . unwrap ( ) ;
437+ let flags_idx = buf. len ( ) ;
438+ buf. extend_from_slice ( & [ 0 ; 4 ] ) ;
441439 buf. write_u32 :: < BigEndian > ( element_type) . unwrap ( ) ;
442440
443441 let mut num_dimensions = 0 ;
@@ -448,14 +446,24 @@ where
448446 }
449447
450448 let num_dimensions = i32:: from_usize ( num_dimensions) ?;
451- ( & mut buf[ dimensions_idx..dimensions_idx + 4 ] )
452- . write_i32 :: < BigEndian > ( num_dimensions)
453- . unwrap ( ) ;
449+ BigEndian :: write_i32 ( & mut buf[ dimensions_idx..] , num_dimensions) ;
454450
451+ let mut has_nulls = false ;
455452 for element in elements {
456- write_nullable ( |buf| serializer ( element, buf) , buf) ?;
453+ write_nullable (
454+ |buf| {
455+ let r = serializer ( element, buf) ;
456+ if let Ok ( IsNull :: Yes ) = r {
457+ has_nulls = true ;
458+ }
459+ r
460+ } ,
461+ buf,
462+ ) ?;
457463 }
458464
465+ BigEndian :: write_i32 ( & mut buf[ flags_idx..] , has_nulls as i32 ) ;
466+
459467 Ok ( ( ) )
460468}
461469
@@ -674,9 +682,7 @@ where
674682 IsNull :: No => i32:: from_usize ( buf. len ( ) - base - 4 ) ?,
675683 IsNull :: Yes => -1 ,
676684 } ;
677- ( & mut buf[ base..base + 4 ] )
678- . write_i32 :: < BigEndian > ( len)
679- . unwrap ( ) ;
685+ BigEndian :: write_i32 ( & mut buf[ base..] , len) ;
680686 }
681687 None => buf. truncate ( base) ,
682688 }
@@ -862,9 +868,7 @@ where
862868 }
863869
864870 let num_points = i32:: from_usize ( num_points) ?;
865- ( & mut buf[ points_idx..] )
866- . write_i32 :: < BigEndian > ( num_points)
867- . unwrap ( ) ;
871+ BigEndian :: write_i32 ( & mut buf[ points_idx..] , num_points) ;
868872
869873 Ok ( ( ) )
870874}
@@ -941,8 +945,8 @@ impl<'a> FallibleIterator for PathPoints<'a> {
941945
942946#[ cfg( test) ]
943947mod test {
944- use std:: collections:: HashMap ;
945948 use fallible_iterator:: FallibleIterator ;
949+ use std:: collections:: HashMap ;
946950
947951 use super :: * ;
948952 use IsNull ;
@@ -1039,7 +1043,6 @@ mod test {
10391043 let mut buf = vec ! [ ] ;
10401044 array_to_sql (
10411045 dimensions. iter ( ) . cloned ( ) ,
1042- true ,
10431046 10 ,
10441047 values. iter ( ) . cloned ( ) ,
10451048 |v, buf| match v {
@@ -1058,4 +1061,40 @@ mod test {
10581061 assert_eq ! ( array. dimensions( ) . collect:: <Vec <_>>( ) . unwrap( ) , dimensions) ;
10591062 assert_eq ! ( array. values( ) . collect:: <Vec <_>>( ) . unwrap( ) , values) ;
10601063 }
1064+
1065+ #[ test]
1066+ fn non_null_array ( ) {
1067+ let dimensions = [
1068+ ArrayDimension {
1069+ len : 1 ,
1070+ lower_bound : 10 ,
1071+ } ,
1072+ ArrayDimension {
1073+ len : 2 ,
1074+ lower_bound : 0 ,
1075+ } ,
1076+ ] ;
1077+ let values = [ Some ( & b"hola" [ ..] ) , Some ( & b"hello" [ ..] ) ] ;
1078+
1079+ let mut buf = vec ! [ ] ;
1080+ array_to_sql (
1081+ dimensions. iter ( ) . cloned ( ) ,
1082+ 10 ,
1083+ values. iter ( ) . cloned ( ) ,
1084+ |v, buf| match v {
1085+ Some ( v) => {
1086+ buf. extend_from_slice ( v) ;
1087+ Ok ( IsNull :: No )
1088+ }
1089+ None => Ok ( IsNull :: Yes ) ,
1090+ } ,
1091+ & mut buf,
1092+ ) . unwrap ( ) ;
1093+
1094+ let array = array_from_sql ( & buf) . unwrap ( ) ;
1095+ assert_eq ! ( array. has_nulls( ) , false ) ;
1096+ assert_eq ! ( array. element_type( ) , 10 ) ;
1097+ assert_eq ! ( array. dimensions( ) . collect:: <Vec <_>>( ) . unwrap( ) , dimensions) ;
1098+ assert_eq ! ( array. values( ) . collect:: <Vec <_>>( ) . unwrap( ) , values) ;
1099+ }
10611100}
0 commit comments