Skip to main content

geoarrow_geojson/encoder/
multilinestring.rs

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