use core::ffi::CStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum GeomType {
Point = 1,
LineString = 2,
Polygon = 3,
MultiPoint = 4,
MultiLineString = 5,
MultiPolygon = 6,
GeometryCollection = 7,
}
impl GeomType {
pub fn as_str(self) -> &'static str {
let ptr = unsafe { tg_geom_sys::tg_geom_type_string(self.into()) };
if ptr.is_null() {
"Unknown"
} else {
unsafe { CStr::from_ptr(ptr) }.to_str().unwrap_or("Unknown")
}
}
}
impl From<tg_geom_sys::tg_geom_type> for GeomType {
fn from(t: tg_geom_sys::tg_geom_type) -> Self {
match t {
tg_geom_sys::tg_geom_type_TG_POINT => GeomType::Point,
tg_geom_sys::tg_geom_type_TG_LINESTRING => GeomType::LineString,
tg_geom_sys::tg_geom_type_TG_POLYGON => GeomType::Polygon,
tg_geom_sys::tg_geom_type_TG_MULTIPOINT => GeomType::MultiPoint,
tg_geom_sys::tg_geom_type_TG_MULTILINESTRING => GeomType::MultiLineString,
tg_geom_sys::tg_geom_type_TG_MULTIPOLYGON => GeomType::MultiPolygon,
tg_geom_sys::tg_geom_type_TG_GEOMETRYCOLLECTION => GeomType::GeometryCollection,
_ => unreachable!("unknown geometry type: {t}"),
}
}
}
impl From<GeomType> for tg_geom_sys::tg_geom_type {
fn from(t: GeomType) -> Self {
match t {
GeomType::Point => tg_geom_sys::tg_geom_type_TG_POINT,
GeomType::LineString => tg_geom_sys::tg_geom_type_TG_LINESTRING,
GeomType::Polygon => tg_geom_sys::tg_geom_type_TG_POLYGON,
GeomType::MultiPoint => tg_geom_sys::tg_geom_type_TG_MULTIPOINT,
GeomType::MultiLineString => tg_geom_sys::tg_geom_type_TG_MULTILINESTRING,
GeomType::MultiPolygon => tg_geom_sys::tg_geom_type_TG_MULTIPOLYGON,
GeomType::GeometryCollection => tg_geom_sys::tg_geom_type_TG_GEOMETRYCOLLECTION,
}
}
}
impl core::fmt::Display for GeomType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_geom_type_as_str() {
assert_eq!(GeomType::Point.as_str(), "Point");
assert_eq!(GeomType::LineString.as_str(), "LineString");
assert_eq!(GeomType::Polygon.as_str(), "Polygon");
assert_eq!(GeomType::MultiPoint.as_str(), "MultiPoint");
assert_eq!(GeomType::MultiLineString.as_str(), "MultiLineString");
assert_eq!(GeomType::MultiPolygon.as_str(), "MultiPolygon");
assert_eq!(GeomType::GeometryCollection.as_str(), "GeometryCollection");
}
#[test]
fn test_geom_type_repr() {
assert_eq!(GeomType::Point as u32, 1);
assert_eq!(GeomType::LineString as u32, 2);
assert_eq!(GeomType::Polygon as u32, 3);
assert_eq!(GeomType::MultiPoint as u32, 4);
assert_eq!(GeomType::MultiLineString as u32, 5);
assert_eq!(GeomType::MultiPolygon as u32, 6);
assert_eq!(GeomType::GeometryCollection as u32, 7);
}
#[test]
fn test_geom_type_sys_roundtrip() {
let types = [
GeomType::Point,
GeomType::LineString,
GeomType::Polygon,
GeomType::MultiPoint,
GeomType::MultiLineString,
GeomType::MultiPolygon,
GeomType::GeometryCollection,
];
for t in &types {
let sys_type: tg_geom_sys::tg_geom_type = (*t).into();
let back: GeomType = sys_type.into();
assert_eq!(*t, back);
}
}
#[test]
fn test_geom_type_display() {
assert_eq!(format!("{}", GeomType::Point), "Point");
assert_eq!(format!("{}", GeomType::LineString), "LineString");
assert_eq!(format!("{}", GeomType::Polygon), "Polygon");
assert_eq!(format!("{}", GeomType::MultiPoint), "MultiPoint");
assert_eq!(format!("{}", GeomType::MultiLineString), "MultiLineString");
assert_eq!(format!("{}", GeomType::MultiPolygon), "MultiPolygon");
assert_eq!(
format!("{}", GeomType::GeometryCollection),
"GeometryCollection"
);
}
#[test]
fn test_geom_type_debug() {
let debug_str = format!("{:?}", GeomType::Point);
assert!(debug_str.contains("Point"));
}
#[test]
fn test_geom_type_copy() {
let t1 = GeomType::Polygon;
let t2 = t1;
assert_eq!(t1, t2);
}
#[test]
fn test_geom_type_eq() {
assert_eq!(GeomType::Point, GeomType::Point);
assert_ne!(GeomType::Point, GeomType::LineString);
}
}