s2json_core/impls/
shape.rs

1use crate::{
2    Map, PrimitiveShape, PrimitiveShapeType, PrimitiveValue, Shape, ShapeType, Value,
3    ValuePrimitiveType, ValueType,
4};
5use alloc::{string::String, vec};
6
7// ? Primitive Shape
8
9impl PrimitiveShape {
10    /// returns true if the shape is a number type
11    pub fn is_number(&self) -> bool {
12        matches!(
13            self,
14            PrimitiveShape::F64 | PrimitiveShape::F32 | PrimitiveShape::I64 | PrimitiveShape::U64
15        )
16    }
17
18    /// returns true if two shapes are the same. Numeric types are considered the same.
19    pub fn matching_shape(&self, other: &PrimitiveShape) -> bool {
20        self == other || self.is_number() == other.is_number()
21    }
22
23    /// returns the highest order number type
24    pub fn get_highest_order_number(
25        type_a: &PrimitiveShape,
26        type_b: &PrimitiveShape,
27    ) -> PrimitiveShape {
28        if *type_a == PrimitiveShape::F64 || *type_b == PrimitiveShape::F64 {
29            PrimitiveShape::F64
30        } else if *type_a == PrimitiveShape::F32 || *type_b == PrimitiveShape::F32 {
31            PrimitiveShape::F32
32        } else if *type_a == PrimitiveShape::I64 || *type_b == PrimitiveShape::I64 {
33            PrimitiveShape::I64
34        } else {
35            PrimitiveShape::U64
36        }
37    }
38
39    fn merge(&mut self, other: &Self) {
40        if self.is_number() && other.is_number() {
41            *self = Self::get_highest_order_number(self, other);
42        } else if !self.matching_shape(other) {
43            panic!("shape mismatch: {:?} vs {:?}", self, other);
44        }
45        // othewrise, do nothing
46    }
47}
48impl From<&PrimitiveShape> for usize {
49    fn from(shape: &PrimitiveShape) -> Self {
50        match shape {
51            PrimitiveShape::String => 0,
52            PrimitiveShape::U64 => 1,
53            PrimitiveShape::I64 => 2,
54            PrimitiveShape::F32 => 3,
55            PrimitiveShape::F64 => 4,
56            PrimitiveShape::Bool => 5,
57            PrimitiveShape::Null => 6,
58        }
59    }
60}
61impl From<usize> for PrimitiveShape {
62    fn from(num: usize) -> Self {
63        match num {
64            0 => PrimitiveShape::String,
65            1 => PrimitiveShape::U64,
66            2 => PrimitiveShape::I64,
67            3 => PrimitiveShape::F32,
68            4 => PrimitiveShape::F64,
69            5 => PrimitiveShape::Bool,
70            6 => PrimitiveShape::Null,
71            _ => panic!("unknown value: {}", num),
72        }
73    }
74}
75impl From<&PrimitiveValue> for PrimitiveShape {
76    fn from(val: &PrimitiveValue) -> Self {
77        match val {
78            PrimitiveValue::String(_) => PrimitiveShape::String,
79            PrimitiveValue::U64(_) => PrimitiveShape::U64,
80            PrimitiveValue::I64(_) => PrimitiveShape::I64,
81            PrimitiveValue::F32(_) => PrimitiveShape::F32,
82            PrimitiveValue::F64(_) => PrimitiveShape::F64,
83            PrimitiveValue::Bool(_) => PrimitiveShape::Bool,
84            PrimitiveValue::Null => PrimitiveShape::Null,
85        }
86    }
87}
88
89// ? Shape Primitive Type
90
91impl From<&ValuePrimitiveType> for PrimitiveShapeType {
92    fn from(val: &ValuePrimitiveType) -> Self {
93        match val {
94            ValuePrimitiveType::Primitive(prim) => PrimitiveShapeType::Primitive(prim.into()),
95            ValuePrimitiveType::NestedPrimitive(nested) => {
96                let mut nested_map = Map::new();
97                for (key, value) in nested.iter() {
98                    nested_map.insert(key.into(), value.into());
99                }
100                PrimitiveShapeType::NestedPrimitive(nested_map)
101            }
102        }
103    }
104}
105impl PrimitiveShapeType {
106    fn merge(&mut self, other: &Self) {
107        match (self, other) {
108            (
109                PrimitiveShapeType::Primitive(self_prim),
110                PrimitiveShapeType::Primitive(other_prim),
111            ) => {
112                self_prim.merge(other_prim);
113            }
114            (
115                PrimitiveShapeType::NestedPrimitive(self_nested),
116                PrimitiveShapeType::NestedPrimitive(other_nested),
117            ) => {
118                for (key, value) in other_nested.iter() {
119                    if self_nested.contains_key(key) {
120                        self_nested.get_mut(key).unwrap().merge(value);
121                    } else {
122                        self_nested.insert(key.clone(), value.clone());
123                    }
124                }
125            }
126            _ => panic!("shape mismatch"),
127        }
128    }
129}
130
131// ? Shape Type
132
133impl Default for ShapeType {
134    fn default() -> Self {
135        ShapeType::Primitive(PrimitiveShape::Null)
136    }
137}
138impl From<&ValueType> for ShapeType {
139    fn from(val: &ValueType) -> Self {
140        match val {
141            ValueType::Primitive(prim) => ShapeType::Primitive(prim.into()),
142            ValueType::Nested(nested) => {
143                let mut nested_map: Map<String, ShapeType> = Map::new();
144                for (key, value) in nested.iter() {
145                    nested_map.insert(key.into(), value.into());
146                }
147                ShapeType::Nested(nested_map)
148            }
149            ValueType::Array(array) => {
150                let validated = validate_types(array);
151                ShapeType::Array(vec![validated])
152            }
153        }
154    }
155}
156impl ShapeType {
157    fn merge(&mut self, other: &Self) {
158        match (self, other) {
159            (Self::Primitive(a), Self::Primitive(b)) => a.merge(b),
160            (Self::Array(a), Self::Array(b)) => {
161                a.first_mut().unwrap().merge(b.first().unwrap());
162            }
163            (Self::Nested(a), Self::Nested(b)) => a.merge(b),
164            _ => panic!("Can't merge"),
165        };
166    }
167}
168
169// ? Shape
170
171impl From<&Value> for Shape {
172    fn from(val: &Value) -> Self {
173        let mut shape = Shape::new();
174        for (key, value) in val.iter() {
175            shape.insert(key.into(), value.into());
176        }
177
178        shape
179    }
180}
181impl From<&[Value]> for Shape {
182    fn from(val: &[Value]) -> Self {
183        let mut shape = Shape::new();
184        for v in val {
185            shape.merge(&(v.into()));
186        }
187        shape
188    }
189}
190impl Shape {
191    /// Merge two shapes
192    pub fn merge(&mut self, other: &Self) {
193        for (key, value) in other.iter() {
194            self.entry(key.clone())
195                .and_modify(|val| val.merge(value))
196                .or_insert_with(|| value.clone());
197        }
198    }
199}
200
201//? Primitive Value
202
203impl PrimitiveValue {
204    /// Get the default primitive value from a shape
205    pub fn default_from_shape(shape: &PrimitiveShape) -> Self {
206        match shape {
207            PrimitiveShape::String => PrimitiveValue::String(String::new()),
208            PrimitiveShape::U64 => PrimitiveValue::U64(0),
209            PrimitiveShape::I64 => PrimitiveValue::I64(0),
210            PrimitiveShape::F32 => PrimitiveValue::F32(0.0),
211            PrimitiveShape::F64 => PrimitiveValue::F64(0.0),
212            PrimitiveShape::Bool => PrimitiveValue::Bool(false),
213            PrimitiveShape::Null => PrimitiveValue::Null,
214        }
215    }
216
217    fn matching_shape(&self, other: &PrimitiveValue) -> bool {
218        matches!(
219            (self, other),
220            (PrimitiveValue::String(_), PrimitiveValue::String(_))
221                | (PrimitiveValue::U64(_), PrimitiveValue::U64(_))
222                | (PrimitiveValue::I64(_), PrimitiveValue::I64(_))
223                | (PrimitiveValue::F32(_), PrimitiveValue::F32(_))
224                | (PrimitiveValue::F64(_), PrimitiveValue::F64(_))
225                | (PrimitiveValue::Bool(_), PrimitiveValue::Bool(_))
226                | (PrimitiveValue::Null, PrimitiveValue::Null)
227        )
228    }
229}
230impl From<&PrimitiveValue> for PrimitiveValue {
231    fn from(mval: &PrimitiveValue) -> Self {
232        match mval {
233            PrimitiveValue::String(string) => PrimitiveValue::String(string.clone()),
234            PrimitiveValue::U64(usigned) => PrimitiveValue::U64(*usigned),
235            PrimitiveValue::I64(signed) => PrimitiveValue::I64(*signed),
236            PrimitiveValue::F32(float) => PrimitiveValue::F32(*float),
237            PrimitiveValue::F64(double) => PrimitiveValue::F64(*double),
238            PrimitiveValue::Bool(boolean) => PrimitiveValue::Bool(*boolean),
239            PrimitiveValue::Null => PrimitiveValue::Null,
240        }
241    }
242}
243
244// ? Value Primitive Type
245
246impl ValuePrimitiveType {
247    fn same_nested(&self, nested: &Map<String, PrimitiveValue>) -> bool {
248        match self {
249            ValuePrimitiveType::Primitive(_) => false,
250            ValuePrimitiveType::NestedPrimitive(val) => {
251                for (key, val) in val.iter() {
252                    if !val.matching_shape(nested.get(key).unwrap()) {
253                        return false;
254                    }
255                }
256                true
257            }
258        }
259    }
260}
261
262// ? ValueType
263
264impl ValueType {
265    /// Get the default value type from a shape
266    pub fn default_from_shape(shape: &ShapeType) -> Self {
267        match shape {
268            ShapeType::Primitive(shape) => {
269                ValueType::Primitive(PrimitiveValue::default_from_shape(shape))
270            }
271            ShapeType::Array(_) => ValueType::Array(vec![]),
272            ShapeType::Nested(shape) => ValueType::Nested(Value::default_from_shape(shape)),
273        }
274    }
275}
276impl From<&PrimitiveValue> for ValueType {
277    fn from(mval: &PrimitiveValue) -> Self {
278        ValueType::Primitive(mval.into())
279    }
280}
281impl From<&ValueType> for PrimitiveValue {
282    fn from(val: &ValueType) -> Self {
283        match val {
284            ValueType::Primitive(val) => val.into(),
285            _ => PrimitiveValue::Null,
286        }
287    }
288}
289
290// ? Value
291
292impl Value {
293    /// Get the default value from a shape
294    pub fn default_from_shape(shape: &Shape) -> Self {
295        let mut value = Value::new();
296        for (key, shape_type) in shape.iter() {
297            value.insert(key.into(), ValueType::default_from_shape(shape_type));
298        }
299        value
300    }
301}
302
303//? The Following are utility functions when the user doesn't pre-define the Properties/M-Value
304//? Shapes to store:
305
306/// This is primarily to check if the type is a primitive.
307/// If the primitive is a number, find the "depth", the most complex is f64, then i64, then u64.
308/// Otherwise, if the primitives don't match, throw an error.
309/// If the type is NOT a primitive, ensure that all types in the array match
310/// returns - a single type from the list to validate the correct type to be parsed from values later
311pub fn validate_types(types: &[ValuePrimitiveType]) -> PrimitiveShapeType {
312    match types.first() {
313        Some(ValuePrimitiveType::Primitive(primitive)) => {
314            let mut base: PrimitiveShape = primitive.into();
315            let is_number = base.is_number();
316            for t in types {
317                match t {
318                    ValuePrimitiveType::Primitive(t_prim) => {
319                        let prim_shape = t_prim.into();
320                        if !base.matching_shape(&prim_shape) {
321                            panic!("All types must be the same");
322                        } else if is_number {
323                            base = PrimitiveShape::get_highest_order_number(&base, &prim_shape);
324                        }
325                        // otherwise do nothing
326                    }
327                    _ => panic!("All types must be the same"),
328                }
329            }
330
331            PrimitiveShapeType::Primitive(base)
332        }
333        Some(ValuePrimitiveType::NestedPrimitive(nested)) => {
334            // iterate and check if each following types match
335            for t in types[1..].iter() {
336                if !t.same_nested(nested) {
337                    panic!("All types must be the same");
338                }
339            }
340
341            (&ValuePrimitiveType::NestedPrimitive(nested.clone())).into()
342        }
343        None => PrimitiveShapeType::Primitive(PrimitiveShape::Null),
344    }
345}