gistools/readers/json/
mod.rs

1/// Large JSON Parsing
2pub mod large_json;
3/// NewLine Delimited JSON Reader
4pub mod line_delimited;
5
6use crate::{geometry::ConvertFeature, parsers::FeatureReader};
7use alloc::{vec, vec::Vec};
8pub use large_json::*;
9pub use line_delimited::*;
10use s2json::{
11    Feature, FeatureCollection, Features, JSONCollection, MValue, Properties, S2FeatureCollection,
12    VectorFeature,
13};
14use serde::{Deserialize, de::DeserializeOwned};
15
16/// Error type for ToGisJSON
17#[derive(Debug, Deserialize)]
18pub enum ToGISJSONError {
19    /// Invalid JSON
20    InvalidJSON,
21}
22
23/// # Convert strings to (Geo|S2)JSON
24///
25/// ## Description
26/// Converts a String or &str to a JSONCollection, FeatureCollection or Feature. Supports S2 and WGS84 JSON
27///
28/// ## Usage
29///
30/// This trait allows for a lot of flexibility in how you can parse your data.
31/// - [`ToGisJSON::to_gis_json`]: Converts an input into a [`JSONCollection`]
32/// - [`ToGisJSON::to_feature_collection`]: Converts an input into a [`FeatureCollection`]
33/// - [`ToGisJSON::to_s2_feature_collection`]: Converts an input into a [`S2FeatureCollection`]
34/// - [`ToGisJSON::to_feature`]: Converts an input into a [`Feature`]
35/// - [`ToGisJSON::to_vector_feature`]: Converts an input into a [`VectorFeature`]
36/// - [`ToGisJSON::to_features`]: Converts an input into a [`Features`]
37pub trait ToGisJSON {
38    /// Converts a String to a JSONCollection. Supports S2 and WGS84 JSON
39    fn to_gis_json<
40        M: Clone + DeserializeOwned,
41        P: Clone + Default + DeserializeOwned,
42        D: Clone + Default + DeserializeOwned,
43    >(
44        &self,
45    ) -> Result<JSONCollection<M, P, D>, ToGISJSONError>;
46    /// Converts a String to a FeatureCollection
47    fn to_feature_collection<
48        M: Clone + DeserializeOwned,
49        P: Clone + Default + DeserializeOwned,
50        D: Clone + Default + DeserializeOwned,
51    >(
52        &self,
53    ) -> Result<FeatureCollection<M, P, D>, ToGISJSONError>;
54    /// Converts a String to a FeatureCollection
55    fn to_s2_feature_collection<
56        M: Clone + DeserializeOwned,
57        P: Clone + Default + DeserializeOwned,
58        D: Clone + Default + DeserializeOwned,
59    >(
60        &self,
61    ) -> Result<S2FeatureCollection<M, P, D>, ToGISJSONError>;
62    /// Converts a String to a Feature
63    fn to_feature<
64        M: Clone + DeserializeOwned,
65        P: Clone + Default + DeserializeOwned,
66        D: Clone + Default + DeserializeOwned,
67    >(
68        &self,
69    ) -> Result<Feature<M, P, D>, ToGISJSONError>;
70    /// Converts a String to a VectorFeature
71    fn to_vector_feature<
72        M: Clone + DeserializeOwned,
73        P: Clone + Default + DeserializeOwned,
74        D: Clone + Default + DeserializeOwned,
75    >(
76        &self,
77    ) -> Result<VectorFeature<M, P, D>, ToGISJSONError>;
78    /// Converts a String to a WMFeature
79    fn to_features<
80        M: Clone + DeserializeOwned,
81        P: Clone + Default + DeserializeOwned,
82        D: Clone + Default + DeserializeOwned,
83    >(
84        &self,
85    ) -> Result<Features<M, P, D>, ToGISJSONError>;
86}
87
88impl ToGisJSON for &str {
89    fn to_gis_json<
90        M: Clone + DeserializeOwned,
91        P: Clone + Default + DeserializeOwned,
92        D: Clone + Default + DeserializeOwned,
93    >(
94        &self,
95    ) -> Result<JSONCollection<M, P, D>, ToGISJSONError> {
96        serde_json::from_str(self).map_err(|_| ToGISJSONError::InvalidJSON)
97    }
98
99    fn to_feature_collection<
100        M: Clone + DeserializeOwned,
101        P: Clone + Default + DeserializeOwned,
102        D: Clone + Default + DeserializeOwned,
103    >(
104        &self,
105    ) -> Result<FeatureCollection<M, P, D>, ToGISJSONError> {
106        serde_json::from_str(self).map_err(|_| ToGISJSONError::InvalidJSON)
107    }
108
109    fn to_s2_feature_collection<
110        M: Clone + DeserializeOwned,
111        P: Clone + Default + DeserializeOwned,
112        D: Clone + Default + DeserializeOwned,
113    >(
114        &self,
115    ) -> Result<S2FeatureCollection<M, P, D>, ToGISJSONError> {
116        serde_json::from_str(self).map_err(|_| ToGISJSONError::InvalidJSON)
117    }
118
119    fn to_feature<
120        M: Clone + DeserializeOwned,
121        P: Clone + Default + DeserializeOwned,
122        D: Clone + Default + DeserializeOwned,
123    >(
124        &self,
125    ) -> Result<Feature<M, P, D>, ToGISJSONError> {
126        serde_json::from_str(self).map_err(|_| ToGISJSONError::InvalidJSON)
127    }
128
129    fn to_vector_feature<
130        M: Clone + DeserializeOwned,
131        P: Clone + Default + DeserializeOwned,
132        D: Clone + Default + DeserializeOwned,
133    >(
134        &self,
135    ) -> Result<VectorFeature<M, P, D>, ToGISJSONError> {
136        serde_json::from_str(self).map_err(|_| ToGISJSONError::InvalidJSON)
137    }
138
139    fn to_features<
140        M: Clone + DeserializeOwned,
141        P: Clone + Default + DeserializeOwned,
142        D: Clone + Default + DeserializeOwned,
143    >(
144        &self,
145    ) -> Result<Features<M, P, D>, ToGISJSONError> {
146        serde_json::from_str(self).map_err(|_| ToGISJSONError::InvalidJSON)
147    }
148}
149
150/// # JSON Collection Reader
151///
152/// ## Description
153/// Parse (Geo|S2)JSON.
154///
155/// Data parsed using the [`ToGisJSON`] trait can be coerced into this struct
156///
157/// Implements the [`FeatureReader`] trait
158///
159/// ## Usage
160/// ```rust
161/// use gistools::{parsers::FeatureReader, readers::{ToGisJSON, JSONCollectionReader}};
162/// use s2json::{MValue, MValueCompatible, Feature};
163/// use serde::{Deserialize, Serialize};
164///
165/// #[derive(Debug, Default, Clone, PartialEq, MValueCompatible, Serialize, Deserialize)]
166/// struct Test {
167///     name: String,
168/// }
169///
170/// let json_str = r#"{
171///     "type": "Feature",
172///     "geometry": {
173///         "type": "Point",
174///         "coordinates": [100.0, 0.0]
175///     },
176///     "properties": {
177///         "name": "Tokyo"
178///     }
179/// }"#;
180/// let mut json: Feature<(), Test, MValue> = json_str.to_feature().unwrap();
181///
182/// let collection = JSONCollectionReader::from(&mut json);
183/// let features: Vec<_> = collection.iter().collect();
184/// assert_eq!(features.len(), 1);
185/// ```
186#[derive(Debug, Clone)]
187pub struct JSONCollectionReader<
188    M: Clone = (),
189    P: Clone + Default = Properties,
190    D: Clone + Default = MValue,
191> {
192    /// Collection of features
193    pub features: Vec<VectorFeature<M, P, D>>,
194}
195impl<M: Clone, P: Clone + Default, D: Clone + Default> JSONCollectionReader<M, P, D> {
196    /// Get the length of the collection
197    pub fn len(&self) -> usize {
198        self.features.len()
199    }
200
201    /// Check if the collection is empty
202    pub fn is_empty(&self) -> bool {
203        self.features.is_empty()
204    }
205
206    /// Mutable iterator
207    pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, VectorFeature<M, P, D>> {
208        self.features.iter_mut()
209    }
210}
211impl<M: Clone, P: Clone + Default, D: Clone + Default> From<&mut JSONCollection<M, P, D>>
212    for JSONCollectionReader<M, P, D>
213{
214    fn from(collection: &mut JSONCollection<M, P, D>) -> Self {
215        let mut features: Vec<VectorFeature<M, P, D>> = vec![];
216        match collection {
217            JSONCollection::FeatureCollection(collection) => {
218                for feature in &mut collection.features {
219                    match feature {
220                        Features::Feature(feature) => {
221                            features.push(feature.to_vector(Some(true)));
222                        }
223                        Features::VectorFeature(vf) => {
224                            features.push(core::mem::take(vf));
225                        }
226                    }
227                }
228            }
229            JSONCollection::S2FeatureCollection(collection) => {
230                features.extend(core::mem::take(&mut collection.features));
231            }
232            JSONCollection::Feature(feature) => {
233                features.push(feature.to_vector(Some(true)));
234            }
235            JSONCollection::VectorFeature(vf) => {
236                features.push(core::mem::take(vf));
237            }
238        };
239
240        JSONCollectionReader { features }
241    }
242}
243impl<M: Clone + Default, P: Clone + Default, D: Clone + Default>
244    From<&mut FeatureCollection<M, P, D>> for JSONCollectionReader<M, P, D>
245{
246    fn from(collection: &mut FeatureCollection<M, P, D>) -> JSONCollectionReader<M, P, D> {
247        JSONCollectionReader::from(&mut JSONCollection::FeatureCollection(core::mem::take(
248            collection,
249        )))
250    }
251}
252impl<M: Clone + Default, P: Clone + Default, D: Clone + Default>
253    From<&mut S2FeatureCollection<M, P, D>> for JSONCollectionReader<M, P, D>
254{
255    fn from(collection: &mut S2FeatureCollection<M, P, D>) -> JSONCollectionReader<M, P, D> {
256        JSONCollectionReader::from(&mut JSONCollection::S2FeatureCollection(core::mem::take(
257            collection,
258        )))
259    }
260}
261impl<M: Clone, P: Clone + Default, D: Clone + Default> From<&mut VectorFeature<M, P, D>>
262    for JSONCollectionReader<M, P, D>
263{
264    fn from(collection: &mut VectorFeature<M, P, D>) -> JSONCollectionReader<M, P, D> {
265        JSONCollectionReader::from(&mut JSONCollection::VectorFeature(core::mem::take(collection)))
266    }
267}
268impl<M: Clone, P: Clone + Default, D: Clone + Default> From<&mut Feature<M, P, D>>
269    for JSONCollectionReader<M, P, D>
270{
271    fn from(feature: &mut Feature<M, P, D>) -> JSONCollectionReader<M, P, D> {
272        JSONCollectionReader::from(&mut JSONCollection::Feature(core::mem::take(feature)))
273    }
274}
275impl<M: Clone, P: Clone + Default, D: Clone + Default> IntoIterator
276    for JSONCollectionReader<M, P, D>
277{
278    type Item = VectorFeature<M, P, D>;
279    type IntoIter = alloc::vec::IntoIter<Self::Item>;
280
281    fn into_iter(self) -> Self::IntoIter {
282        self.features.into_iter()
283    }
284}
285/// The JSON Iterator tool
286#[derive(Debug)]
287pub struct JSONCollectionIterator<
288    'a,
289    M: Clone + DeserializeOwned,
290    P: Clone + Default + DeserializeOwned,
291    D: Clone + Default + DeserializeOwned,
292> {
293    reader: &'a JSONCollectionReader<M, P, D>,
294    offset: usize,
295    size: usize,
296}
297impl<
298    M: Clone + DeserializeOwned,
299    P: Clone + Default + DeserializeOwned,
300    D: Clone + Default + DeserializeOwned,
301> Iterator for JSONCollectionIterator<'_, M, P, D>
302{
303    type Item = VectorFeature<M, P, D>;
304
305    fn next(&mut self) -> Option<Self::Item> {
306        if self.offset >= self.size {
307            return None;
308        }
309        self.offset += 1;
310        self.reader.features.get(self.offset - 1).cloned()
311    }
312}
313/// A feature reader trait with a callback-based approach
314impl<
315    M: Clone + DeserializeOwned,
316    P: Clone + Default + DeserializeOwned,
317    D: Clone + Default + DeserializeOwned,
318> FeatureReader<M, P, D> for JSONCollectionReader<M, P, D>
319{
320    type FeatureIterator<'a>
321        = JSONCollectionIterator<'a, M, P, D>
322    where
323        M: 'a,
324        P: 'a,
325        D: 'a;
326
327    fn iter(&self) -> Self::FeatureIterator<'_> {
328        JSONCollectionIterator { reader: self, offset: 0, size: self.features.len() }
329    }
330
331    fn par_iter(&self, pool_size: usize, thread_id: usize) -> Self::FeatureIterator<'_> {
332        let start = self.len() * thread_id / pool_size;
333        let end = self.len() * (thread_id + 1) / pool_size;
334        JSONCollectionIterator { reader: self, offset: start, size: end }
335    }
336}