Skip to main content

geoarrow_geojson/encoder/
geometry.rs

1use arrow_json::Encoder;
2use geo_traits::GeometryTrait;
3use geoarrow_array::GeoArrowArrayAccessor;
4use geoarrow_array::array::GeometryArray;
5
6use crate::encoder::geometrycollection::encode_geometry_collection;
7use crate::encoder::linestring::encode_line_string;
8use crate::encoder::multilinestring::encode_multi_line_string;
9use crate::encoder::multipoint::encode_multi_point;
10use crate::encoder::multipolygon::encode_multi_polygon;
11use crate::encoder::point::encode_point;
12use crate::encoder::polygon::encode_polygon;
13use crate::encoder::rect::encode_rect;
14
15// An [Encoder] for [GeometryArray].
16pub struct GeometryEncoder(GeometryArray);
17
18impl GeometryEncoder {
19    pub fn new(array: GeometryArray) -> Self {
20        Self(array)
21    }
22}
23
24impl Encoder for GeometryEncoder {
25    fn encode(&mut self, idx: usize, out: &mut Vec<u8>) {
26        let geom = self.0.value(idx).unwrap();
27        encode_geometry(&geom, out);
28    }
29}
30
31/// Encode a Geometry geometry including the `type: Geometry` header
32pub(crate) fn encode_geometry(geom: &impl GeometryTrait<T = f64>, out: &mut Vec<u8>) {
33    use geo_traits::GeometryType::*;
34
35    match geom.as_type() {
36        Point(geom) => encode_point(geom, out),
37        LineString(geom) => {
38            encode_line_string(geom, out);
39        }
40        Polygon(geom) => encode_polygon(geom, out),
41        MultiPoint(geom) => encode_multi_point(geom, out),
42        MultiLineString(geom) => encode_multi_line_string(geom, out),
43        MultiPolygon(geom) => encode_multi_polygon(geom, out),
44        GeometryCollection(geom) => encode_geometry_collection(geom, out),
45        Rect(geom) => encode_rect(geom, out),
46        Triangle(_) | Line(_) => unreachable!(),
47    }
48}
49
50#[cfg(test)]
51mod test {
52    use std::str::FromStr;
53
54    use geoarrow_array::test::geometry::array;
55    use geoarrow_schema::CoordType;
56
57    use super::*;
58
59    #[test]
60    fn encode_geometry() {
61        let mut encoder = GeometryEncoder::new(array(CoordType::Separated, false));
62
63        let mut out = vec![];
64        encoder.encode(0, &mut out);
65        let s = String::from_utf8(out).unwrap();
66        let expected = r#"{"type":"Point","coordinates":[30,10]}"#;
67        assert_eq!(s, expected);
68
69        geojson::Geometry::from_str(expected).expect("Should be valid GeoJSON");
70    }
71}