1use core::ffi::CStr;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6#[repr(u32)]
7pub enum GeomType {
8 Point = 1,
9 LineString = 2,
10 Polygon = 3,
11 MultiPoint = 4,
12 MultiLineString = 5,
13 MultiPolygon = 6,
14 GeometryCollection = 7,
15}
16
17impl GeomType {
18 pub fn as_str(self) -> &'static str {
19 let ptr = unsafe { tg_geom_sys::tg_geom_type_string(self.into()) };
20 if ptr.is_null() {
21 "Unknown"
22 } else {
23 unsafe { CStr::from_ptr(ptr) }.to_str().unwrap_or("Unknown")
24 }
25 }
26}
27
28impl From<tg_geom_sys::tg_geom_type> for GeomType {
29 fn from(t: tg_geom_sys::tg_geom_type) -> Self {
30 match t {
31 tg_geom_sys::tg_geom_type_TG_POINT => GeomType::Point,
32 tg_geom_sys::tg_geom_type_TG_LINESTRING => GeomType::LineString,
33 tg_geom_sys::tg_geom_type_TG_POLYGON => GeomType::Polygon,
34 tg_geom_sys::tg_geom_type_TG_MULTIPOINT => GeomType::MultiPoint,
35 tg_geom_sys::tg_geom_type_TG_MULTILINESTRING => GeomType::MultiLineString,
36 tg_geom_sys::tg_geom_type_TG_MULTIPOLYGON => GeomType::MultiPolygon,
37 tg_geom_sys::tg_geom_type_TG_GEOMETRYCOLLECTION => GeomType::GeometryCollection,
38 _ => unreachable!("unknown geometry type: {t}"),
39 }
40 }
41}
42
43impl From<GeomType> for tg_geom_sys::tg_geom_type {
44 fn from(t: GeomType) -> Self {
45 match t {
46 GeomType::Point => tg_geom_sys::tg_geom_type_TG_POINT,
47 GeomType::LineString => tg_geom_sys::tg_geom_type_TG_LINESTRING,
48 GeomType::Polygon => tg_geom_sys::tg_geom_type_TG_POLYGON,
49 GeomType::MultiPoint => tg_geom_sys::tg_geom_type_TG_MULTIPOINT,
50 GeomType::MultiLineString => tg_geom_sys::tg_geom_type_TG_MULTILINESTRING,
51 GeomType::MultiPolygon => tg_geom_sys::tg_geom_type_TG_MULTIPOLYGON,
52 GeomType::GeometryCollection => tg_geom_sys::tg_geom_type_TG_GEOMETRYCOLLECTION,
53 }
54 }
55}
56
57impl core::fmt::Display for GeomType {
58 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
59 write!(f, "{}", self.as_str())
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 #[test]
68 fn test_geom_type_as_str() {
69 assert_eq!(GeomType::Point.as_str(), "Point");
70 assert_eq!(GeomType::LineString.as_str(), "LineString");
71 assert_eq!(GeomType::Polygon.as_str(), "Polygon");
72 assert_eq!(GeomType::MultiPoint.as_str(), "MultiPoint");
73 assert_eq!(GeomType::MultiLineString.as_str(), "MultiLineString");
74 assert_eq!(GeomType::MultiPolygon.as_str(), "MultiPolygon");
75 assert_eq!(GeomType::GeometryCollection.as_str(), "GeometryCollection");
76 }
77
78 #[test]
79 fn test_geom_type_repr() {
80 assert_eq!(GeomType::Point as u32, 1);
81 assert_eq!(GeomType::LineString as u32, 2);
82 assert_eq!(GeomType::Polygon as u32, 3);
83 assert_eq!(GeomType::MultiPoint as u32, 4);
84 assert_eq!(GeomType::MultiLineString as u32, 5);
85 assert_eq!(GeomType::MultiPolygon as u32, 6);
86 assert_eq!(GeomType::GeometryCollection as u32, 7);
87 }
88
89 #[test]
90 fn test_geom_type_sys_roundtrip() {
91 let types = [
92 GeomType::Point,
93 GeomType::LineString,
94 GeomType::Polygon,
95 GeomType::MultiPoint,
96 GeomType::MultiLineString,
97 GeomType::MultiPolygon,
98 GeomType::GeometryCollection,
99 ];
100 for t in &types {
101 let sys_type: tg_geom_sys::tg_geom_type = (*t).into();
102 let back: GeomType = sys_type.into();
103 assert_eq!(*t, back);
104 }
105 }
106
107 #[test]
108 fn test_geom_type_display() {
109 assert_eq!(format!("{}", GeomType::Point), "Point");
110 assert_eq!(format!("{}", GeomType::LineString), "LineString");
111 assert_eq!(format!("{}", GeomType::Polygon), "Polygon");
112 assert_eq!(format!("{}", GeomType::MultiPoint), "MultiPoint");
113 assert_eq!(format!("{}", GeomType::MultiLineString), "MultiLineString");
114 assert_eq!(format!("{}", GeomType::MultiPolygon), "MultiPolygon");
115 assert_eq!(
116 format!("{}", GeomType::GeometryCollection),
117 "GeometryCollection"
118 );
119 }
120
121 #[test]
122 fn test_geom_type_debug() {
123 let debug_str = format!("{:?}", GeomType::Point);
124 assert!(debug_str.contains("Point"));
125 }
126
127 #[test]
128 fn test_geom_type_copy() {
129 let t1 = GeomType::Polygon;
130 let t2 = t1;
131 assert_eq!(t1, t2);
132 }
133
134 #[test]
135 fn test_geom_type_eq() {
136 assert_eq!(GeomType::Point, GeomType::Point);
137 assert_ne!(GeomType::Point, GeomType::LineString);
138 }
139}