Skip to main content

geoarrow_geojson/encoder/
point.rs

1use std::io::Write;
2
3use arrow_json::Encoder;
4use geo_traits::{CoordTrait, PointTrait};
5use geoarrow_array::GeoArrowArrayAccessor;
6use geoarrow_array::array::PointArray;
7
8// An [Encoder] for [PointArray].
9pub struct PointEncoder(PointArray);
10
11impl PointEncoder {
12    pub fn new(array: PointArray) -> Self {
13        Self(array)
14    }
15}
16
17impl Encoder for PointEncoder {
18    fn encode(&mut self, idx: usize, out: &mut Vec<u8>) {
19        let point = self.0.value(idx).unwrap();
20        encode_point(&point, out);
21    }
22}
23
24pub(crate) fn encode_point(point: &impl PointTrait<T = f64>, out: &mut Vec<u8>) {
25    out.extend(br#"{"type":"Point","coordinates":"#);
26    let coord = point
27        .coord()
28        .expect("POINT EMPTY not yet supported in GeoJSON writer");
29    encode_coord(&coord, out);
30    out.push(b'}');
31}
32
33pub(crate) fn encode_coord(coord: &impl CoordTrait<T = f64>, out: &mut Vec<u8>) {
34    out.push(b'[');
35    let dim_size = coord.dim().size();
36    for n in 0..dim_size {
37        write!(out, "{}", coord.nth_or_panic(n)).unwrap();
38        if n < dim_size - 1 {
39            out.push(b',');
40        }
41    }
42    out.push(b']');
43}
44
45#[cfg(test)]
46mod test {
47    use std::str::FromStr;
48
49    use geoarrow_array::test::point::array;
50    use geoarrow_schema::{CoordType, Dimension};
51
52    use super::*;
53
54    #[test]
55    fn encode_point() {
56        let mut encoder = PointEncoder::new(array(CoordType::Separated, Dimension::XY));
57
58        let mut out = vec![];
59        encoder.encode(0, &mut out);
60        let s = String::from_utf8(out).unwrap();
61        let expected = r#"{"type":"Point","coordinates":[30,10]}"#;
62        assert_eq!(s, expected);
63
64        geojson::Geometry::from_str(expected).expect("Should be valid GeoJSON");
65    }
66
67    #[test]
68    fn encode_point_xyz() {
69        let mut encoder = PointEncoder::new(array(CoordType::Separated, Dimension::XYZ));
70
71        let mut out = vec![];
72        encoder.encode(0, &mut out);
73        let s = String::from_utf8(out).unwrap();
74        let expected = r#"{"type":"Point","coordinates":[30,10,40]}"#;
75        assert_eq!(s, expected);
76
77        geojson::Geometry::from_str(expected).expect("Should be valid GeoJSON");
78    }
79}