geoarrow_geojson/encoder/
multipoint.rs1use arrow_json::Encoder;
2use geo_traits::{MultiPointTrait, PointTrait};
3use geoarrow_array::GeoArrowArrayAccessor;
4use geoarrow_array::array::MultiPointArray;
5
6use crate::encoder::point::encode_coord;
7
8pub struct MultiPointEncoder(MultiPointArray);
10
11impl MultiPointEncoder {
12 pub fn new(array: MultiPointArray) -> Self {
13 Self(array)
14 }
15}
16
17impl Encoder for MultiPointEncoder {
18 fn encode(&mut self, idx: usize, out: &mut Vec<u8>) {
19 let geom = self.0.value(idx).unwrap();
20 encode_multi_point(&geom, out);
21 }
22}
23
24pub(crate) fn encode_multi_point(geom: &impl MultiPointTrait<T = f64>, out: &mut Vec<u8>) {
26 out.extend(br#"{"type":"MultiPoint","coordinates":"#);
27 encode_points(geom.points(), out);
28 out.push(b'}');
29}
30
31fn encode_points(
33 points: impl ExactSizeIterator<Item = impl PointTrait<T = f64>>,
34 out: &mut Vec<u8>,
35) {
36 out.push(b'[');
37 let num_coords = points.len();
38 for (idx, point) in points.enumerate() {
39 encode_coord(&point.coord().expect("Empty points not supported."), out);
40 if idx < num_coords - 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::multipoint::array;
52 use geoarrow_schema::{CoordType, Dimension};
53
54 use super::*;
55
56 #[test]
57 fn encode_multipoint() {
58 let mut encoder = MultiPointEncoder::new(array(CoordType::Separated, Dimension::XY));
59
60 let mut out = vec![];
61 encoder.encode(0, &mut out);
62 let s = String::from_utf8(out).unwrap();
63 let expected = r#"{"type":"MultiPoint","coordinates":[[30,10]]}"#;
64 assert_eq!(s, expected);
65
66 geojson::Geometry::from_str(expected).expect("Should be valid GeoJSON");
67 }
68}