1use std::collections::BTreeMap;
4use std::str::FromStr;
5
6use geo_types::Geometry;
7use serde::ser::SerializeMap as _;
8use serde::{Deserialize, Serialize};
9use serde_json::{Number, Value};
10
11use crate::decoder::PropValueRef;
12use crate::{LendingIterator, MltResult, ParsedLayer};
13
14#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
16pub struct FeatureCollection {
17 #[serde(rename = "type")]
18 pub ty: String,
19 pub features: Vec<Feature>,
20}
21
22impl FeatureCollection {
23 pub fn from_layers<'a>(layers: impl IntoIterator<Item = ParsedLayer<'a>>) -> MltResult<Self> {
26 let mut features = Vec::new();
27 for layer in layers {
28 let Some(parsed) = layer.into_layer01() else {
29 continue;
30 };
31 let layer_name = parsed.name();
32 let extent = parsed.extent().get();
33 let mut feat_iter = parsed.iter_features();
34 while let Some(feat) = feat_iter.next() {
35 let feat = feat?;
36 let mut properties = BTreeMap::new();
37 for p in feat.iter_properties() {
38 properties.insert(p.name().to_string(), p.value().into());
39 }
40 properties.insert("_layer".into(), Value::String(layer_name.to_string()));
41 properties.insert("_extent".into(), Value::Number(extent.into()));
42 features.push(Feature {
43 geometry: feat.geometry().clone(),
44 id: feat.id(),
45 properties,
46 ty: "Feature".into(),
47 });
48 }
49 }
50 Ok(Self {
51 features,
52 ty: "FeatureCollection".into(),
53 })
54 }
55
56 pub fn equals(&self, other: &Self) -> Result<bool, serde_json::Error> {
57 let self_val = normalize_tiny_floats(serde_json::to_value(self)?);
58 let other_val = normalize_tiny_floats(serde_json::to_value(other)?);
59 Ok(json_values_equal(&self_val, &other_val))
60 }
61}
62
63impl FromStr for FeatureCollection {
64 type Err = serde_json::Error;
65
66 fn from_str(s: &str) -> Result<Self, Self::Err> {
67 serde_json::from_str(s)
68 }
69}
70
71#[derive(Debug, Clone, PartialEq, Deserialize)]
73pub struct Feature {
74 #[serde(with = "geom_serde")]
75 pub geometry: Geometry<i32>,
76 #[serde(default, skip_serializing_if = "Option::is_none")]
77 pub id: Option<u64>,
78 #[serde(default)]
79 pub properties: BTreeMap<String, Value>,
80 #[serde(rename = "type")]
81 pub ty: String,
82}
83
84struct Geom32Wire<'a>(&'a Geometry<i32>);
85impl Serialize for Geom32Wire<'_> {
86 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
87 geom_serde::serialize(self.0, s)
88 }
89}
90
91impl Serialize for Feature {
93 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
94 let len = 3 + usize::from(self.id.is_some());
95 let mut map = serializer.serialize_map(Some(len))?;
96 map.serialize_entry("type", &self.ty)?;
97 if let Some(id) = self.id {
98 map.serialize_entry("id", &id)?;
99 }
100 map.serialize_entry("properties", &self.properties)?;
101 map.serialize_entry("geometry", &Geom32Wire(&self.geometry))?;
102 map.end()
103 }
104}
105
106mod geom_serde {
109 use geo_types::{
110 Geometry, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon,
111 };
112 use serde::de::Error as _;
113 use serde::ser::{Error, SerializeMap as _};
114 use serde::{Deserialize, Deserializer, Serializer};
115 use serde_json::Value;
116
117 type Arr = [i32; 2];
118
119 fn ls_arr(ls: &LineString<i32>) -> Vec<Arr> {
120 ls.0.iter().copied().map(Into::into).collect()
121 }
122
123 fn poly_arr(poly: &Polygon<i32>) -> Vec<Vec<Arr>> {
124 std::iter::once(poly.exterior())
125 .chain(poly.interiors())
126 .map(ls_arr)
127 .collect()
128 }
129
130 fn arr_ls(v: Vec<Arr>) -> LineString<i32> {
131 LineString::from(v)
132 }
133
134 fn arr_poly(rings: Vec<Vec<Arr>>) -> Polygon<i32> {
135 let mut it = rings.into_iter();
136 let ext = it.next().map_or_else(|| LineString(vec![]), arr_ls);
137 Polygon::new(ext, it.map(arr_ls).collect())
138 }
139
140 pub fn serialize<S: Serializer>(g: &Geometry<i32>, s: S) -> Result<S::Ok, S::Error> {
141 let mut m = s.serialize_map(Some(2))?;
142 let (ty, coords): (&str, Value) = match g {
143 Geometry::Point(p) => ("Point", serde_json::to_value(Arr::from(*p)).unwrap()),
144 Geometry::LineString(ls) => ("LineString", serde_json::to_value(ls_arr(ls)).unwrap()),
145 Geometry::Polygon(poly) => ("Polygon", serde_json::to_value(poly_arr(poly)).unwrap()),
146 Geometry::MultiPoint(mp) => (
147 "MultiPoint",
148 serde_json::to_value(mp.0.iter().copied().map(Arr::from).collect::<Vec<_>>())
149 .unwrap(),
150 ),
151 Geometry::MultiLineString(mls) => (
152 "MultiLineString",
153 serde_json::to_value(mls.iter().map(ls_arr).collect::<Vec<_>>()).unwrap(),
154 ),
155 Geometry::MultiPolygon(mpoly) => (
156 "MultiPolygon",
157 serde_json::to_value(mpoly.iter().map(poly_arr).collect::<Vec<_>>()).unwrap(),
158 ),
159 Geometry::Line(_)
160 | Geometry::Rect(_)
161 | Geometry::Triangle(_)
162 | Geometry::GeometryCollection(_) => {
163 return Err(Error::custom("unsupported geometry variant"));
164 }
165 };
166 m.serialize_entry("type", ty)?;
167 m.serialize_entry("coordinates", &coords)?;
168 m.end()
169 }
170
171 pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Geometry<i32>, D::Error> {
172 fn parse<T: serde::de::DeserializeOwned, E: serde::de::Error>(v: Value) -> Result<T, E> {
173 serde_json::from_value(v).map_err(E::custom)
174 }
175
176 #[derive(Deserialize)]
177 struct Wire {
178 #[serde(rename = "type")]
179 ty: String,
180 coordinates: Value,
181 }
182
183 let Wire { ty, coordinates: c } = Wire::deserialize(d)?;
184 Ok(match ty.as_str() {
185 "Point" => Geometry::Point(Point::from(parse::<Arr, _>(c)?)),
186 "LineString" => Geometry::LineString(arr_ls(parse(c)?)),
187 "Polygon" => Geometry::Polygon(arr_poly(parse(c)?)),
188 "MultiPoint" => {
189 let v: Vec<Arr> = parse(c)?;
190 Geometry::MultiPoint(MultiPoint(v.into_iter().map(Point::from).collect()))
191 }
192 "MultiLineString" => {
193 let v: Vec<Vec<Arr>> = parse(c)?;
194 Geometry::MultiLineString(MultiLineString(v.into_iter().map(arr_ls).collect()))
195 }
196 "MultiPolygon" => {
197 let v: Vec<Vec<Vec<Arr>>> = parse(c)?;
198 Geometry::MultiPolygon(MultiPolygon(v.into_iter().map(arr_poly).collect()))
199 }
200 _ => {
201 return Err(D::Error::unknown_variant(
202 &ty,
203 &[
204 "Point",
205 "LineString",
206 "Polygon",
207 "MultiPoint",
208 "MultiLineString",
209 "MultiPolygon",
210 ],
211 ));
212 }
213 })
214 }
215}
216
217#[must_use]
219pub fn f32_to_json(f: f32) -> Value {
220 if f.is_nan() {
221 Value::String("f32::NAN".to_owned())
222 } else if f == f32::INFINITY {
223 Value::String("f32::INFINITY".to_owned())
224 } else if f == f32::NEG_INFINITY {
225 Value::String("f32::NEG_INFINITY".to_owned())
226 } else {
227 Number::from_f64(f64::from(f)).expect("finite f32").into()
228 }
229}
230
231#[must_use]
233pub fn f64_to_json(f: f64) -> Value {
234 if f.is_nan() {
235 Value::String("f64::NAN".to_owned())
236 } else if f == f64::INFINITY {
237 Value::String("f64::INFINITY".to_owned())
238 } else if f == f64::NEG_INFINITY {
239 Value::String("f64::NEG_INFINITY".to_owned())
240 } else {
241 Number::from_f64(f).expect("finite f64").into()
242 }
243}
244
245impl From<PropValueRef<'_>> for Value {
246 fn from(v: PropValueRef<'_>) -> Self {
247 match v {
248 PropValueRef::Bool(v) => Self::Bool(v),
249 PropValueRef::I8(v) => Self::from(v),
250 PropValueRef::U8(v) => Self::from(v),
251 PropValueRef::I32(v) => Self::from(v),
252 PropValueRef::U32(v) => Self::from(v),
253 PropValueRef::I64(v) => Self::from(v),
254 PropValueRef::U64(v) => Self::from(v),
255 PropValueRef::F32(v) => f32_to_json(v),
256 PropValueRef::F64(v) => f64_to_json(v),
257 PropValueRef::Str(s) => Self::String(s.to_string()),
258 }
259 }
260}
261
262fn normalize_tiny_floats(value: Value) -> Value {
264 match value {
265 Value::Number(ref n) => {
266 let eps = f64::from(f32::EPSILON);
267 if let Some(f) = n.as_f64()
268 && f.is_finite()
269 && f.abs() < eps
270 {
271 Value::from(0.0)
272 } else {
273 value
274 }
275 }
276 Value::Array(arr) => Value::Array(arr.into_iter().map(normalize_tiny_floats).collect()),
277 Value::Object(obj) => Value::Object(
278 obj.into_iter()
279 .map(|(k, v)| (k, normalize_tiny_floats(v)))
280 .collect(),
281 ),
282 Value::Null | Value::Bool(_) | Value::String(_) => value,
283 }
284}
285
286fn json_values_equal(a: &Value, b: &Value) -> bool {
290 match (a, b) {
291 (Value::Number(na), Value::Number(nb)) if na.is_f64() && nb.is_f64() => {
292 let na = na.as_f64().expect("f64");
293 let nb = nb.as_f64().expect("f64");
294 assert!(
295 !na.is_nan() && !nb.is_nan(),
296 "unexpected non-finite numbers"
297 );
298 let abs_diff = (na - nb).abs();
299 let max_abs = na.abs().max(nb.abs()).max(1.0);
300 abs_diff <= f64::from(f32::EPSILON) * max_abs * 2.0
301 }
302 (Value::Array(aa), Value::Array(ab)) => {
303 aa.len() == ab.len()
304 && aa
305 .iter()
306 .zip(ab.iter())
307 .all(|(x, y)| json_values_equal(x, y))
308 }
309 (Value::Object(ao), Value::Object(bo)) => {
310 ao.len() == bo.len()
311 && ao
312 .iter()
313 .all(|(k, v)| bo.get(k).is_some_and(|w| json_values_equal(v, w)))
314 }
315 _ => a == b,
316 }
317}