tg-geom 0.0.0

Rust bindings for the `TG` Geometry library.
Documentation
//! OGC Simple Feature geometry types.

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);
    }
}