@@ -780,6 +780,111 @@ pub type MultiPolygonM = MultiPolygonT<PointM>;
780
780
pub type MultiPolygonZM = MultiPolygonT < PointZM > ;
781
781
782
782
783
+ /// Generic Geometry Data Type
784
+ #[ derive( Debug ) ]
785
+ pub enum GeometryT < P : postgis:: Point + EwkbRead > {
786
+ Point ( P ) ,
787
+ LineString ( LineStringT < P > ) ,
788
+ Polygon ( PolygonT < P > ) ,
789
+ MultiPoint ( MultiPointT < P > ) ,
790
+ MultiLineString ( MultiLineStringT < P > ) ,
791
+ MultiPolygon ( MultiPolygonT < P > ) ,
792
+ GeometryCollection ( GeometryCollectionT < P > )
793
+ }
794
+
795
+
796
+ impl < P > EwkbRead for GeometryT < P >
797
+ where P : postgis:: Point + EwkbRead
798
+ {
799
+ fn point_type ( ) -> PointType {
800
+ P :: point_type ( )
801
+ }
802
+ fn read_ewkb < R : Read > ( raw : & mut R ) -> Result < Self , Error > {
803
+ let byte_order = try!( raw. read_i8 ( ) ) ;
804
+ let is_be = byte_order == 0i8 ;
805
+
806
+ let type_id = try!( read_u32 ( raw, is_be) ) ;
807
+ let mut srid: Option < i32 > = None ;
808
+ if type_id & 0x20000000 == 0x20000000 {
809
+ srid = Some ( try!( read_i32 ( raw, is_be) ) ) ;
810
+ }
811
+
812
+ let geom = match type_id & 0xff {
813
+ 0x01 => GeometryT :: Point ( P :: read_ewkb_body ( raw, is_be, srid) . unwrap ( ) ) ,
814
+ 0x02 => GeometryT :: LineString ( LineStringT :: < P > :: read_ewkb_body ( raw, is_be, srid) . unwrap ( ) ) ,
815
+ 0x03 => GeometryT :: Polygon ( PolygonT :: read_ewkb_body ( raw, is_be, srid) . unwrap ( ) ) ,
816
+ 0x04 => GeometryT :: MultiPoint ( MultiPointT :: read_ewkb_body ( raw, is_be, srid) . unwrap ( ) ) ,
817
+ 0x05 => GeometryT :: MultiLineString ( MultiLineStringT :: read_ewkb_body ( raw, is_be, srid) . unwrap ( ) ) ,
818
+ 0x06 => GeometryT :: MultiPolygon ( MultiPolygonT :: read_ewkb_body ( raw, is_be, srid) . unwrap ( ) ) ,
819
+ 0x07 => GeometryT :: GeometryCollection ( GeometryCollectionT :: read_ewkb_body ( raw, is_be, srid) . unwrap ( ) ) ,
820
+ _ => return Err ( Error :: Read ( format ! ( "Error reading generic geometry type - unsupported type id {}." , type_id) ) )
821
+ } ;
822
+ Ok ( geom)
823
+ }
824
+ fn read_ewkb_body < R : Read > ( _raw : & mut R , _is_be : bool , _srid : Option < i32 > ) -> Result < Self , Error > {
825
+ panic ! ( "Not used for generic geometry type" )
826
+ }
827
+ }
828
+
829
+ pub type Geometry = GeometryT < Point > ;
830
+ pub type GeometryZ = GeometryT < PointZ > ;
831
+ pub type GeometryM = GeometryT < PointM > ;
832
+ pub type GeometryZM = GeometryT < PointZM > ;
833
+
834
+
835
+ /// GeometryCollection
836
+ #[ derive( Debug ) ]
837
+ pub struct GeometryCollectionT < P : postgis:: Point + EwkbRead > {
838
+ pub geometries : Vec < GeometryT < P > >
839
+ }
840
+
841
+ impl < P > GeometryCollectionT < P >
842
+ where P : postgis:: Point + EwkbRead
843
+ {
844
+ pub fn new ( ) -> GeometryCollectionT < P > {
845
+ GeometryCollectionT { geometries : Vec :: new ( ) }
846
+ }
847
+ }
848
+
849
+ impl < P > EwkbRead for GeometryCollectionT < P >
850
+ where P : postgis:: Point + EwkbRead
851
+ {
852
+ fn point_type ( ) -> PointType {
853
+ P :: point_type ( )
854
+ }
855
+ fn read_ewkb_body < R : Read > ( raw : & mut R , is_be : bool , _srid : Option < i32 > ) -> Result < Self , Error > {
856
+ let mut ret = GeometryCollectionT :: new ( ) ;
857
+ let size = try!( read_u32 ( raw, is_be) ) as usize ;
858
+ for _ in 0 ..size {
859
+ let is_be = try!( raw. read_i8 ( ) ) == 0i8 ;
860
+
861
+ let type_id = try!( read_u32 ( raw, is_be) ) ;
862
+ let mut srid: Option < i32 > = None ;
863
+ if type_id & 0x20000000 == 0x20000000 {
864
+ srid = Some ( try!( read_i32 ( raw, is_be) ) ) ;
865
+ }
866
+ let geom = match type_id & 0xff {
867
+ 0x01 => GeometryT :: Point ( P :: read_ewkb_body ( raw, is_be, srid) . unwrap ( ) ) ,
868
+ 0x02 => GeometryT :: LineString ( LineStringT :: < P > :: read_ewkb_body ( raw, is_be, srid) . unwrap ( ) ) ,
869
+ 0x03 => GeometryT :: Polygon ( PolygonT :: read_ewkb_body ( raw, is_be, srid) . unwrap ( ) ) ,
870
+ 0x04 => GeometryT :: MultiPoint ( MultiPointT :: read_ewkb_body ( raw, is_be, srid) . unwrap ( ) ) ,
871
+ 0x05 => GeometryT :: MultiLineString ( MultiLineStringT :: read_ewkb_body ( raw, is_be, srid) . unwrap ( ) ) ,
872
+ 0x06 => GeometryT :: MultiPolygon ( MultiPolygonT :: read_ewkb_body ( raw, is_be, srid) . unwrap ( ) ) ,
873
+ 0x07 => GeometryT :: GeometryCollection ( GeometryCollectionT :: read_ewkb_body ( raw, is_be, srid) . unwrap ( ) ) ,
874
+ _ => return Err ( Error :: Read ( format ! ( "Error reading generic geometry type - unsupported type id {}." , type_id) ) )
875
+ } ;
876
+ ret. geometries . push ( geom) ;
877
+ }
878
+ Ok ( ret)
879
+ }
880
+ }
881
+
882
+ pub type GeometryCollection = GeometryCollectionT < Point > ;
883
+ pub type GeometryCollectionZ = GeometryCollectionT < PointZ > ;
884
+ pub type GeometryCollectionM = GeometryCollectionT < PointM > ;
885
+ pub type GeometryCollectionZM = GeometryCollectionT < PointZM > ;
886
+
887
+
783
888
#[ test]
784
889
fn test_point_write ( ) {
785
890
// 'POINT (10 -20)'
@@ -943,7 +1048,7 @@ fn test_multipoint_read() {
943
1048
}
944
1049
945
1050
#[ test]
946
- fn test_multline_read ( ) {
1051
+ fn test_multiline_read ( ) {
947
1052
let p = |x, y| Point { x : x, y : y, srid : None } ; // PostGIS doesn't store SRID for sub-geometries
948
1053
// SELECT 'SRID=4326;MULTILINESTRING ((10 -20, 0 -0.5), (0 0, 2 0))'::geometry
949
1054
let ewkb = hex_to_vec ( "0105000020E610000002000000010200000002000000000000000000244000000000000034C00000000000000000000000000000E0BF0102000000020000000000000000000000000000000000000000000000000000400000000000000000" ) ;
@@ -966,6 +1071,46 @@ fn test_multipolygon_read() {
966
1071
assert_eq ! ( multipoly, MultiPolygonT :: <Point > { srid: Some ( 4326 ) , polygons: vec![ poly1, poly2] } ) ;
967
1072
}
968
1073
1074
+ #[ test]
1075
+ fn test_geometrycollection_read ( ) {
1076
+ // SELECT 'GeometryCollection(POINT (10 10),POINT (30 30),LINESTRING (15 15, 20 20))'::geometry
1077
+ let ewkb = hex_to_vec ( "01070000000300000001010000000000000000002440000000000000244001010000000000000000003E400000000000003E400102000000020000000000000000002E400000000000002E4000000000000034400000000000003440" ) ;
1078
+ let geom = GeometryCollectionT :: < Point > :: read_ewkb ( & mut ewkb. as_slice ( ) ) . unwrap ( ) ;
1079
+ assert_eq ! ( format!( "{:?}" , geom) , "GeometryCollectionT { geometries: [Point(Point { x: 10, y: 10, srid: None }), Point(Point { x: 30, y: 30, srid: None }), LineString(LineStringT { points: [Point { x: 15, y: 15, srid: None }, Point { x: 20, y: 20, srid: None }], srid: None })] }" ) ;
1080
+ }
1081
+
1082
+ #[ test]
1083
+ fn test_geometry_read ( ) {
1084
+ // SELECT 'POINT(10 -20 100 1)'::geometry
1085
+ let ewkb = hex_to_vec ( "01010000C0000000000000244000000000000034C00000000000005940000000000000F03F" ) ;
1086
+ let geom = GeometryT :: < PointZM > :: read_ewkb ( & mut ewkb. as_slice ( ) ) . unwrap ( ) ;
1087
+ assert_eq ! ( format!( "{:?}" , geom) , "Point(PointZM { x: 10, y: -20, z: 100, m: 1, srid: None })" ) ;
1088
+ // SELECT 'SRID=4326;LINESTRING (10 -20 100, 0 -0.5 101)'::geometry
1089
+ let ewkb = hex_to_vec ( "01020000A0E610000002000000000000000000244000000000000034C000000000000059400000000000000000000000000000E0BF0000000000405940" ) ;
1090
+ let geom = GeometryT :: < PointZ > :: read_ewkb ( & mut ewkb. as_slice ( ) ) . unwrap ( ) ;
1091
+ assert_eq ! ( format!( "{:?}" , geom) , "LineString(LineStringT { points: [PointZ { x: 10, y: -20, z: 100, srid: Some(4326) }, PointZ { x: 0, y: -0.5, z: 101, srid: Some(4326) }], srid: Some(4326) })" ) ;
1092
+ // SELECT 'SRID=4326;POLYGON ((0 0, 2 0, 2 2, 0 2, 0 0))'::geometry
1093
+ let ewkb = hex_to_vec ( "0103000020E610000001000000050000000000000000000000000000000000000000000000000000400000000000000000000000000000004000000000000000400000000000000000000000000000004000000000000000000000000000000000" ) ;
1094
+ let geom = GeometryT :: < Point > :: read_ewkb ( & mut ewkb. as_slice ( ) ) . unwrap ( ) ;
1095
+ assert_eq ! ( format!( "{:?}" , geom) , "Polygon(PolygonT { rings: [LineStringT { points: [Point { x: 0, y: 0, srid: Some(4326) }, Point { x: 2, y: 0, srid: Some(4326) }, Point { x: 2, y: 2, srid: Some(4326) }, Point { x: 0, y: 2, srid: Some(4326) }, Point { x: 0, y: 0, srid: Some(4326) }], srid: Some(4326) }], srid: Some(4326) })" ) ;
1096
+ // SELECT 'SRID=4326;MULTIPOINT ((10 -20 100), (0 -0.5 101))'::geometry
1097
+ let ewkb = hex_to_vec ( "01040000A0E6100000020000000101000080000000000000244000000000000034C0000000000000594001010000800000000000000000000000000000E0BF0000000000405940" ) ;
1098
+ let geom = GeometryT :: < PointZ > :: read_ewkb ( & mut ewkb. as_slice ( ) ) . unwrap ( ) ;
1099
+ assert_eq ! ( format!( "{:?}" , geom) , "MultiPoint(MultiPointT { points: [PointZ { x: 10, y: -20, z: 100, srid: None }, PointZ { x: 0, y: -0.5, z: 101, srid: None }], srid: Some(4326) })" ) ;
1100
+ // SELECT 'SRID=4326;MULTILINESTRING ((10 -20, 0 -0.5), (0 0, 2 0))'::geometry
1101
+ let ewkb = hex_to_vec ( "0105000020E610000002000000010200000002000000000000000000244000000000000034C00000000000000000000000000000E0BF0102000000020000000000000000000000000000000000000000000000000000400000000000000000" ) ;
1102
+ let geom = GeometryT :: < Point > :: read_ewkb ( & mut ewkb. as_slice ( ) ) . unwrap ( ) ;
1103
+ assert_eq ! ( format!( "{:?}" , geom) , "MultiLineString(MultiLineStringT { lines: [LineStringT { points: [Point { x: 10, y: -20, srid: None }, Point { x: 0, y: -0.5, srid: None }], srid: None }, LineStringT { points: [Point { x: 0, y: 0, srid: None }, Point { x: 2, y: 0, srid: None }], srid: None }], srid: Some(4326) })" ) ;
1104
+ // SELECT 'SRID=4326;MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((10 10, -2 10, -2 -2, 10 -2, 10 10)))'::geometry
1105
+ let ewkb = hex_to_vec ( "0106000020E610000002000000010300000001000000050000000000000000000000000000000000000000000000000000400000000000000000000000000000004000000000000000400000000000000000000000000000004000000000000000000000000000000000010300000001000000050000000000000000002440000000000000244000000000000000C0000000000000244000000000000000C000000000000000C0000000000000244000000000000000C000000000000024400000000000002440" ) ;
1106
+ let geom = GeometryT :: < Point > :: read_ewkb ( & mut ewkb. as_slice ( ) ) . unwrap ( ) ;
1107
+ assert_eq ! ( format!( "{:?}" , geom) , "MultiPolygon(MultiPolygonT { polygons: [PolygonT { rings: [LineStringT { points: [Point { x: 0, y: 0, srid: None }, Point { x: 2, y: 0, srid: None }, Point { x: 2, y: 2, srid: None }, Point { x: 0, y: 2, srid: None }, Point { x: 0, y: 0, srid: None }], srid: None }], srid: None }, PolygonT { rings: [LineStringT { points: [Point { x: 10, y: 10, srid: None }, Point { x: -2, y: 10, srid: None }, Point { x: -2, y: -2, srid: None }, Point { x: 10, y: -2, srid: None }, Point { x: 10, y: 10, srid: None }], srid: None }], srid: None }], srid: Some(4326) })" ) ;
1108
+ // SELECT 'GeometryCollection(POINT (10 10),POINT (30 30),LINESTRING (15 15, 20 20))'::geometry
1109
+ let ewkb = hex_to_vec ( "01070000000300000001010000000000000000002440000000000000244001010000000000000000003E400000000000003E400102000000020000000000000000002E400000000000002E4000000000000034400000000000003440" ) ;
1110
+ let geom = GeometryT :: < Point > :: read_ewkb ( & mut ewkb. as_slice ( ) ) . unwrap ( ) ;
1111
+ assert_eq ! ( format!( "{:?}" , geom) , "GeometryCollection(GeometryCollectionT { geometries: [Point(Point { x: 10, y: 10, srid: None }), Point(Point { x: 30, y: 30, srid: None }), LineString(LineStringT { points: [Point { x: 15, y: 15, srid: None }, Point { x: 20, y: 20, srid: None }], srid: None })] })" ) ;
1112
+ }
1113
+
969
1114
#[ test]
970
1115
fn test_iterators ( ) {
971
1116
// Iterator traits:
0 commit comments