s2json_core/
value.rs

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