1
1
//! Conversions to and from Postgres's binary format for various types.
2
- use byteorder:: { ReadBytesExt , WriteBytesExt , BigEndian } ;
2
+ use byteorder:: { BigEndian , ByteOrder , ReadBytesExt , WriteBytesExt } ;
3
3
use fallible_iterator:: FallibleIterator ;
4
+ use std:: boxed:: Box as StdBox ;
4
5
use std:: error:: Error ;
5
6
use std:: str;
6
- use std:: boxed:: Box as StdBox ;
7
7
8
- use { Oid , IsNull , write_nullable , FromUsize } ;
8
+ use { write_nullable , FromUsize , IsNull , Oid } ;
9
9
10
10
const RANGE_UPPER_UNBOUNDED : u8 = 0b0001_0000 ;
11
11
const RANGE_LOWER_UNBOUNDED : u8 = 0b0000_1000 ;
@@ -189,9 +189,7 @@ where
189
189
}
190
190
191
191
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) ;
195
193
196
194
Ok ( ( ) )
197
195
}
@@ -424,7 +422,6 @@ pub fn uuid_from_sql(buf: &[u8]) -> Result<[u8; 16], StdBox<Error + Sync + Send>
424
422
#[ inline]
425
423
pub fn array_to_sql < T , I , J , F > (
426
424
dimensions : I ,
427
- has_nulls : bool ,
428
425
element_type : Oid ,
429
426
elements : J ,
430
427
mut serializer : F ,
@@ -437,7 +434,8 @@ where
437
434
{
438
435
let dimensions_idx = buf. len ( ) ;
439
436
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 ] ) ;
441
439
buf. write_u32 :: < BigEndian > ( element_type) . unwrap ( ) ;
442
440
443
441
let mut num_dimensions = 0 ;
@@ -448,14 +446,24 @@ where
448
446
}
449
447
450
448
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) ;
454
450
451
+ let mut has_nulls = false ;
455
452
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
+ ) ?;
457
463
}
458
464
465
+ BigEndian :: write_i32 ( & mut buf[ flags_idx..] , has_nulls as i32 ) ;
466
+
459
467
Ok ( ( ) )
460
468
}
461
469
@@ -674,9 +682,7 @@ where
674
682
IsNull :: No => i32:: from_usize ( buf. len ( ) - base - 4 ) ?,
675
683
IsNull :: Yes => -1 ,
676
684
} ;
677
- ( & mut buf[ base..base + 4 ] )
678
- . write_i32 :: < BigEndian > ( len)
679
- . unwrap ( ) ;
685
+ BigEndian :: write_i32 ( & mut buf[ base..] , len) ;
680
686
}
681
687
None => buf. truncate ( base) ,
682
688
}
@@ -862,9 +868,7 @@ where
862
868
}
863
869
864
870
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) ;
868
872
869
873
Ok ( ( ) )
870
874
}
@@ -941,8 +945,8 @@ impl<'a> FallibleIterator for PathPoints<'a> {
941
945
942
946
#[ cfg( test) ]
943
947
mod test {
944
- use std:: collections:: HashMap ;
945
948
use fallible_iterator:: FallibleIterator ;
949
+ use std:: collections:: HashMap ;
946
950
947
951
use super :: * ;
948
952
use IsNull ;
@@ -1039,7 +1043,6 @@ mod test {
1039
1043
let mut buf = vec ! [ ] ;
1040
1044
array_to_sql (
1041
1045
dimensions. iter ( ) . cloned ( ) ,
1042
- true ,
1043
1046
10 ,
1044
1047
values. iter ( ) . cloned ( ) ,
1045
1048
|v, buf| match v {
@@ -1058,4 +1061,40 @@ mod test {
1058
1061
assert_eq ! ( array. dimensions( ) . collect:: <Vec <_>>( ) . unwrap( ) , dimensions) ;
1059
1062
assert_eq ! ( array. values( ) . collect:: <Vec <_>>( ) . unwrap( ) , values) ;
1060
1063
}
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
+ }
1061
1100
}
0 commit comments