Skip to main content

geoarrow_geojson/encoder/
geometrycollection.rs

1use arrow_json::Encoder;
2use geo_traits::GeometryCollectionTrait;
3use geoarrow_array::GeoArrowArrayAccessor;
4use geoarrow_array::array::GeometryCollectionArray;
5
6use crate::encoder::geometry::encode_geometry;
7
8// An [Encoder] for [GeometryCollectionArray].
9pub struct GeometryCollectionEncoder(GeometryCollectionArray);
10
11impl GeometryCollectionEncoder {
12    pub fn new(array: GeometryCollectionArray) -> Self {
13        Self(array)
14    }
15}
16
17impl Encoder for GeometryCollectionEncoder {
18    fn encode(&mut self, idx: usize, out: &mut Vec<u8>) {
19        let geom = self.0.value(idx).unwrap();
20        encode_geometry_collection(&geom, out);
21    }
22}
23
24/// Encode a GeometryCollection geometry including the `type: GeometryCollection` header
25pub(crate) fn encode_geometry_collection(
26    geom: &impl GeometryCollectionTrait<T = f64>,
27    out: &mut Vec<u8>,
28) {
29    out.extend(br#"{"type":"GeometryCollection","geometries":"#);
30    encode_geometries(geom, out);
31    out.push(b'}');
32}
33
34/// Encode the coordinates of a LineString geometry
35fn encode_geometries(gc: &impl GeometryCollectionTrait<T = f64>, out: &mut Vec<u8>) {
36    out.push(b'[');
37    let num_geometries = gc.num_geometries();
38    for (idx, geom) in gc.geometries().enumerate() {
39        encode_geometry(&geom, out);
40        if idx < num_geometries - 1 {
41            out.push(b',');
42        }
43    }
44    out.push(b']');
45}
46
47#[cfg(test)]
48mod test {
49    use std::str::FromStr;
50
51    use geoarrow_array::test::geometrycollection::array;
52    use geoarrow_schema::{CoordType, Dimension};
53
54    use super::*;
55
56    #[test]
57    fn encode_geometry_collection() {
58        let mut encoder =
59            GeometryCollectionEncoder::new(array(CoordType::Separated, Dimension::XY, false));
60
61        let mut out = vec![];
62        encoder.encode(0, &mut out);
63        let s = String::from_utf8(out).unwrap();
64        let expected = r#"{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[30,10]}]}"#;
65        assert_eq!(s, expected);
66        // println!("{}", s);
67
68        geojson::Geometry::from_str(expected).expect("Should be valid GeoJSON");
69    }
70}