gistools/geometry/
values.rs

1use serde::{Deserialize, Serialize};
2
3use alloc::collections::BTreeMap;
4use alloc::string::String;
5use alloc::vec::Vec;
6
7/// Primitive types supported by Properties
8#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
9#[serde(untagged)]
10pub enum PrimitiveValue {
11    /// String type utf8 encoded
12    String(String),
13    /// unsigned 64 bit integer
14    U64(u64),
15    /// signed 64 bit integer
16    I64(i64),
17    /// floating point number
18    F32(f32),
19    /// double precision floating point number
20    F64(f64),
21    /// boolean
22    Bool(bool),
23    /// null
24    Null,
25}
26
27/// Arrays may contain either a primitive or an object whose values are primitives
28#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
29#[serde(untagged)]
30pub enum ValuePrimitiveType {
31    /// Primitive type
32    Primitive(PrimitiveValue),
33    /// Nested shape that can only contain primitives
34    NestedPrimitive(BTreeMap<String, PrimitiveValue>),
35}
36
37/// Supports primitive types `string`, `number`, `boolean`, `null`
38/// May be an array of those types, or an object of those types
39/// Object keys are always strings, values can be any basic type, an array, or a nested object.
40/// Array values must all be the same type.
41#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
42#[serde(untagged)]
43pub enum ValueType {
44    /// A primitive value
45    Primitive(PrimitiveValue),
46    /// An array of values
47    Array(Vec<ValuePrimitiveType>),
48    /// A nested object
49    Nested(Value),
50}
51
52/// Shape design
53pub type Value = BTreeMap<String, ValueType>;
54/// Shape of a features properties object
55pub type Properties = Value;
56/// Shape of a feature's M-Values object
57pub type MValue = Value;
58
59/// LineString Properties Shape
60pub type LineStringMValues = Vec<MValue>;
61/// MultiLineString MValues Shape
62pub type MultiLineStringMValues = Vec<LineStringMValues>;
63/// Polygon MValues Shape
64pub type PolygonMValues = Vec<LineStringMValues>;
65/// MultiPolygon MValues Shape
66pub type MultiPolygonMValues = Vec<PolygonMValues>;
67
68/// All possible M-Value shapes
69#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
70#[serde(untagged)]
71pub enum MValues {
72    /// Single M-Value
73    MValue(MValue),
74    /// LineString M-Value
75    LineStringMValues(LineStringMValues),
76    /// MultiLineString M-Value
77    MultiLineStringMValues(MultiLineStringMValues),
78    /// Polygon M-Value
79    PolygonMValues(PolygonMValues),
80    /// MultiPolygon M-Value
81    MultiPolygonMValues(MultiPolygonMValues),
82}
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87
88    #[test]
89    fn primitive_value() {
90        let prim_value = PrimitiveValue::String("test".into());
91        assert_eq!(prim_value, PrimitiveValue::String("test".into()));
92        let prim_value = PrimitiveValue::U64(1);
93        assert_eq!(prim_value, PrimitiveValue::U64(1));
94        let prim_value = PrimitiveValue::I64(1);
95        assert_eq!(prim_value, PrimitiveValue::I64(1));
96        let prim_value = PrimitiveValue::F32(1.0);
97        assert_eq!(prim_value, PrimitiveValue::F32(1.0));
98        let prim_value = PrimitiveValue::F64(1.0);
99        assert_eq!(prim_value, PrimitiveValue::F64(1.0));
100        let prim_value = PrimitiveValue::Bool(true);
101        assert_eq!(prim_value, PrimitiveValue::Bool(true));
102        let prim_value = PrimitiveValue::Null;
103        assert_eq!(prim_value, PrimitiveValue::Null);
104    }
105
106    #[test]
107    fn primitive_string_serialize() {
108        let prim_value = PrimitiveValue::String("test".into());
109        let serialized = serde_json::to_string(&prim_value).unwrap();
110        assert_eq!(serialized, "\"test\"");
111        let deserialize = serde_json::from_str::<PrimitiveValue>(&serialized).unwrap();
112        assert_eq!(deserialize, PrimitiveValue::String("test".into()));
113    }
114
115    #[test]
116    fn primitive_u64_serialize() {
117        let prim_value = PrimitiveValue::U64(1);
118        let serialized = serde_json::to_string(&prim_value).unwrap();
119        assert_eq!(serialized, "1");
120        let deserialize = serde_json::from_str::<PrimitiveValue>(&serialized).unwrap();
121        assert_eq!(deserialize, PrimitiveValue::U64(1));
122    }
123
124    #[test]
125    fn primitive_i64_serialize() {
126        let prim_value = PrimitiveValue::I64(-1);
127        let serialized = serde_json::to_string(&prim_value).unwrap();
128        assert_eq!(serialized, "-1");
129        let deserialize = serde_json::from_str::<PrimitiveValue>(&serialized).unwrap();
130        assert_eq!(deserialize, PrimitiveValue::I64(-1));
131    }
132
133    #[test]
134    fn primitive_f32_serialize() {
135        let prim_value = PrimitiveValue::F32(1.0);
136        let serialized = serde_json::to_string(&prim_value).unwrap();
137        assert_eq!(serialized, "1.0");
138        let deserialize = serde_json::from_str::<PrimitiveValue>(&serialized).unwrap();
139        assert_eq!(deserialize, PrimitiveValue::F32(1.0));
140    }
141
142    #[test]
143    fn primitive_f64_serialize() {
144        let prim_value = PrimitiveValue::F64(-135435345435345345.0);
145        let serialized = serde_json::to_string(&prim_value).unwrap();
146        assert_eq!(serialized, "-1.3543534543534534e17");
147        let deserialize = serde_json::from_str::<PrimitiveValue>(&serialized).unwrap();
148        assert_eq!(deserialize, PrimitiveValue::F32(-1.3543534e17));
149    }
150
151    #[test]
152    fn primitive_bool_serialize() {
153        let prim_value = PrimitiveValue::Bool(true);
154        let serialized = serde_json::to_string(&prim_value).unwrap();
155        assert_eq!(serialized, "true");
156        let deserialize = serde_json::from_str::<PrimitiveValue>(&serialized).unwrap();
157        assert_eq!(deserialize, PrimitiveValue::Bool(true));
158    }
159
160    #[test]
161    fn primitive_null_serialize() {
162        let prim_value = PrimitiveValue::Null;
163        let serialized = serde_json::to_string(&prim_value).unwrap();
164        assert_eq!(serialized, "null");
165        let deserialize = serde_json::from_str::<PrimitiveValue>(&serialized).unwrap();
166        assert_eq!(deserialize, PrimitiveValue::Null);
167    }
168
169    #[test]
170    fn value_serialize() {
171        let value: Value = BTreeMap::from([
172            ("type".into(), ValueType::Primitive(PrimitiveValue::String("Point".into()))),
173            ("coordinates".into(), ValueType::Primitive(PrimitiveValue::F32(1.0))),
174        ]);
175        let serialized = serde_json::to_string(&value).unwrap();
176        assert_eq!(serialized, "{\"coordinates\":1.0,\"type\":\"Point\"}");
177        let deserialize = serde_json::from_str::<Value>(&serialized).unwrap();
178        assert_eq!(deserialize, value);
179
180        let value_str = r#"
181        {
182            "class": "ocean",
183            "offset": 22,
184            "info": {
185                "name": "Pacific Ocean",
186                "value": 22.2
187            }
188        }
189        "#;
190
191        let deserialize = serde_json::from_str::<Value>(value_str).unwrap();
192        assert_eq!(
193            deserialize,
194            BTreeMap::from([
195                ("class".into(), ValueType::Primitive(PrimitiveValue::String("ocean".into()))),
196                ("offset".into(), ValueType::Primitive(PrimitiveValue::U64(22))),
197                (
198                    "info".into(),
199                    ValueType::Nested(BTreeMap::from([
200                        (
201                            "name".into(),
202                            ValueType::Primitive(PrimitiveValue::String("Pacific Ocean".into()))
203                        ),
204                        ("value".into(), ValueType::Primitive(PrimitiveValue::F32(22.2))),
205                    ]))
206                ),
207            ])
208        );
209    }
210}