ovtile/open/
shape.rs

1use crate::{
2    mapbox::{Properties as MapboxProperties, Value as MapboxValue},
3    open::{ColumnCacheReader, ColumnCacheWriter, ColumnValue},
4    CustomOrdWrapper,
5};
6
7use serde::{Deserialize, Serialize};
8
9use alloc::collections::BTreeMap;
10use alloc::string::String;
11use alloc::vec;
12use alloc::vec::Vec;
13
14//? Shape
15
16// Shapes exist solely to deconstruct and rebuild objects.
17//
18// Shape limitations:
19// - all keys are strings.
20// - all values are either:
21// - - primitive types: strings, numbers (f32, f64, u64, i64), true, false, or null
22// - - sub types: an array of a shape or a nested object which is itself a shape
23// - - if the sub type is an array, ensure all elements are of the same type
24// The interfaces below help describe how shapes are built by the user.
25
26/// Primitive types that can be found in a shape
27#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
28#[serde(rename_all = "lowercase")]
29pub enum PrimitiveShape {
30    /// String type utf8 encoded
31    String,
32    /// unsigned 64 bit integer
33    U64,
34    /// signed 64 bit integer
35    I64,
36    /// floating point number
37    F32,
38    /// double precision floating point number
39    F64,
40    /// boolean
41    Bool,
42    /// null
43    Null,
44}
45impl PrimitiveShape {
46    fn encode(&self, shape_store: &mut Vec<ColumnValue>, _cache: &mut ColumnCacheWriter) {
47        shape_store.push(ShapePair::encode(ShapeDefinition::Primitive, self.into()).into());
48    }
49
50    fn decode(shape_store: &mut Vec<usize>) -> Self {
51        let shape_pair = ShapePair::decode(shape_store.remove(0));
52        shape_pair.count_or_col.into()
53    }
54
55    /// returns true if the shape is a number type
56    pub fn is_number(&self) -> bool {
57        matches!(
58            self,
59            PrimitiveShape::F64 | PrimitiveShape::F32 | PrimitiveShape::I64 | PrimitiveShape::U64
60        )
61    }
62
63    /// returns true if two shapes are the same. Numeric types are considered the same.
64    pub fn matching_shape(&self, other: &PrimitiveShape) -> bool {
65        self == other || self.is_number() == other.is_number()
66    }
67
68    /// returns the highest order number type
69    pub fn get_highest_order_number(
70        type_a: &PrimitiveShape,
71        type_b: &PrimitiveShape,
72    ) -> PrimitiveShape {
73        if *type_a == PrimitiveShape::F64 || *type_b == PrimitiveShape::F64 {
74            PrimitiveShape::F64
75        } else if *type_a == PrimitiveShape::F32 || *type_b == PrimitiveShape::F32 {
76            PrimitiveShape::F32
77        } else if *type_a == PrimitiveShape::I64 || *type_b == PrimitiveShape::I64 {
78            PrimitiveShape::I64
79        } else {
80            PrimitiveShape::U64
81        }
82    }
83
84    fn merge(&mut self, other: &Self) {
85        if self.is_number() && other.is_number() {
86            *self = Self::get_highest_order_number(self, other);
87        } else if !self.matching_shape(other) {
88            #[tarpaulin::skip]
89            panic!("shape mismatch: {:?} vs {:?}", self, other);
90        }
91        // othewrise, do nothing
92    }
93}
94impl From<&PrimitiveShape> for usize {
95    fn from(shape: &PrimitiveShape) -> Self {
96        match shape {
97            PrimitiveShape::String => 0,
98            PrimitiveShape::U64 => 1,
99            PrimitiveShape::I64 => 2,
100            PrimitiveShape::F32 => 3,
101            PrimitiveShape::F64 => 4,
102            PrimitiveShape::Bool => 5,
103            PrimitiveShape::Null => 6,
104        }
105    }
106}
107impl From<PrimitiveValue> for PrimitiveShape {
108    fn from(val: PrimitiveValue) -> Self {
109        match val {
110            PrimitiveValue::String(_) => PrimitiveShape::String,
111            PrimitiveValue::U64(_) => PrimitiveShape::U64,
112            PrimitiveValue::I64(_) => PrimitiveShape::I64,
113            PrimitiveValue::F32(_) => PrimitiveShape::F32,
114            PrimitiveValue::F64(_) => PrimitiveShape::F64,
115            PrimitiveValue::Bool(_) => PrimitiveShape::Bool,
116            PrimitiveValue::Null => PrimitiveShape::Null,
117        }
118    }
119}
120impl From<usize> for PrimitiveShape {
121    fn from(num: usize) -> Self {
122        match num {
123            0 => PrimitiveShape::String,
124            1 => PrimitiveShape::U64,
125            2 => PrimitiveShape::I64,
126            3 => PrimitiveShape::F32,
127            4 => PrimitiveShape::F64,
128            5 => PrimitiveShape::Bool,
129            6 => PrimitiveShape::Null,
130            #[tarpaulin::skip]
131            _ => panic!("unknown value: {}", num),
132        }
133    }
134}
135
136/// Arrays may contain either a primitive or an object whose values are primitives
137#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
138#[serde(untagged)]
139pub enum ShapePrimitiveType {
140    /// Primitive type
141    Primitive(PrimitiveShape),
142    /// Nested shape that can only contain primitives
143    NestedPrimitive(BTreeMap<String, PrimitiveShape>),
144}
145impl From<ValuePrimitiveType> for ShapePrimitiveType {
146    fn from(val: ValuePrimitiveType) -> Self {
147        match val {
148            ValuePrimitiveType::Primitive(prim) => ShapePrimitiveType::Primitive(prim.into()),
149            ValuePrimitiveType::NestedPrimitive(nested) => {
150                let mut nested_map = BTreeMap::new();
151                for (key, value) in nested {
152                    nested_map.insert(key, value.into());
153                }
154                ShapePrimitiveType::NestedPrimitive(nested_map)
155            }
156        }
157    }
158}
159impl ShapePrimitiveType {
160    fn encode(&self, shape_store: &mut Vec<ColumnValue>, cache: &mut ColumnCacheWriter) {
161        match self {
162            Self::Primitive(prim) => prim.encode(shape_store, cache),
163            Self::NestedPrimitive(nested) => {
164                shape_store.push(ShapePair::encode(ShapeDefinition::Object, nested.len()).into());
165                for (key, value) in nested {
166                    shape_store.push(cache.add_string(key.clone()).into());
167                    value.encode(shape_store, cache);
168                }
169            }
170        }
171    }
172
173    fn decode(store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self {
174        let shape_pair = ShapePair::decode(store.remove(0));
175        match shape_pair.p_type {
176            ShapeDefinition::Primitive => {
177                Self::Primitive(PrimitiveShape::from(shape_pair.count_or_col))
178            }
179            ShapeDefinition::Object => {
180                let mut nested = BTreeMap::new();
181                for _ in 0..shape_pair.count_or_col {
182                    nested.insert(cache.get_string(store.remove(0)), PrimitiveShape::decode(store));
183                }
184                Self::NestedPrimitive(nested)
185            }
186            #[tarpaulin::skip]
187            _ => panic!("Unknown shape definition: {:?}", shape_pair),
188        }
189    }
190
191    fn merge(&mut self, other: &Self) {
192        match (self, other) {
193            (
194                ShapePrimitiveType::Primitive(self_prim),
195                ShapePrimitiveType::Primitive(other_prim),
196            ) => {
197                self_prim.merge(other_prim);
198            }
199            (
200                ShapePrimitiveType::NestedPrimitive(self_nested),
201                ShapePrimitiveType::NestedPrimitive(other_nested),
202            ) => {
203                for (key, value) in other_nested {
204                    if self_nested.contains_key(key) {
205                        self_nested.get_mut(key).unwrap().merge(value);
206                    } else {
207                        self_nested.insert(key.clone(), value.clone());
208                    }
209                }
210            }
211            #[tarpaulin::skip]
212            _ => panic!("shape mismatch"),
213        }
214    }
215}
216
217/// Shape types that can be found in a shapes object.
218/// Either a primitive, an array containing any type, or a nested shape.
219/// If the type is an array, all elements must be the same type
220#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
221#[serde(untagged)]
222pub enum ShapeType {
223    /// Primitive type
224    Primitive(PrimitiveShape),
225    /// Nested shape that can only contain primitives
226    Array(Vec<ShapePrimitiveType>),
227    /// Nested shape
228    Nested(Shape),
229}
230impl From<ValueType> for ShapeType {
231    fn from(val: ValueType) -> Self {
232        match val {
233            ValueType::Primitive(prim) => ShapeType::Primitive(prim.into()),
234            ValueType::Nested(nested) => {
235                let mut nested_map: BTreeMap<String, ShapeType> = BTreeMap::new();
236                for (key, value) in nested.0 {
237                    nested_map.insert(key, value.into());
238                }
239                ShapeType::Nested(Shape(nested_map))
240            }
241            ValueType::Array(array) => {
242                let validated = validate_types(&array);
243                ShapeType::Array(vec![validated])
244            }
245        }
246    }
247}
248impl ShapeType {
249    fn encode(&self, shape_store: &mut Vec<ColumnValue>, cache: &mut ColumnCacheWriter) {
250        match self {
251            Self::Primitive(prim) => prim.encode(shape_store, cache),
252            Self::Array(array) => {
253                shape_store.push(0.into());
254                array.first().unwrap().encode(shape_store, cache);
255            }
256            Self::Nested(nested) => {
257                nested.encode(shape_store, cache);
258            }
259        }
260    }
261
262    fn decode(store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self {
263        let code = store.remove(0);
264        let shape_pair = ShapePair::decode(code);
265        match shape_pair.p_type {
266            ShapeDefinition::Primitive => {
267                Self::Primitive(PrimitiveShape::from(shape_pair.count_or_col))
268            }
269            ShapeDefinition::Array => Self::Array(vec![ShapePrimitiveType::decode(store, cache)]),
270            ShapeDefinition::Object => {
271                // reinsert code because shape will check it again
272                store.insert(0, code);
273                Self::Nested(Shape::decode(store, cache))
274            }
275        }
276    }
277
278    fn merge(&mut self, other: &Self) {
279        match (self, other) {
280            (Self::Primitive(a), Self::Primitive(b)) => a.merge(b),
281            (Self::Array(a), Self::Array(b)) => {
282                a.first_mut().unwrap().merge(b.first().unwrap());
283            }
284            (Self::Nested(a), Self::Nested(b)) => a.merge(b),
285            #[tarpaulin::skip]
286            _ => panic!("Can't merge"),
287        };
288    }
289}
290
291/// The Shape Object
292#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq)]
293pub struct Shape(pub BTreeMap<String, ShapeType>);
294impl From<Value> for Shape {
295    fn from(val: Value) -> Self {
296        let mut shape = BTreeMap::new();
297        for (key, value) in val.0 {
298            shape.insert(key, value.into());
299        }
300        Shape(shape)
301    }
302}
303impl From<&[Value]> for Shape {
304    fn from(val: &[Value]) -> Self {
305        let mut shape = Shape(BTreeMap::new());
306        for v in val {
307            shape.merge(&v.clone().into());
308        }
309        shape
310    }
311}
312impl Shape {
313    /// Encode the shape
314    pub fn encode(&self, shape_store: &mut Vec<ColumnValue>, cache: &mut ColumnCacheWriter) {
315        shape_store.push(ShapePair::encode(ShapeDefinition::Object, self.0.len()).into());
316        for (key, value) in &self.0 {
317            shape_store.push(cache.add_string(key.clone()).into());
318            value.encode(shape_store, cache);
319        }
320    }
321
322    /// Decode the shape
323    pub fn decode(store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self {
324        let mut map = BTreeMap::<String, ShapeType>::new();
325        let shape_pair = ShapePair::decode(store.remove(0));
326        if shape_pair.p_type != ShapeDefinition::Object {
327            panic!("expected object shape")
328        }
329        for _ in 0..shape_pair.count_or_col {
330            let key = cache.get_string(store.remove(0));
331            let shape = ShapeType::decode(store, cache);
332            map.insert(key, shape);
333        }
334        Shape(map)
335    }
336
337    /// Merge two shapes
338    pub fn merge(&mut self, other: &Self) {
339        for (key, value) in &other.0 {
340            self.0
341                .entry(key.clone())
342                .and_modify(|val| val.merge(value))
343                .or_insert_with(|| value.clone());
344        }
345    }
346}
347
348/// Create shapes
349///
350/// Used by Layer's and Feature's M-Values
351/// Must be an object of key values
352/// all keys will be the same, values will be different
353/// A layer's Shape defines what the properties look like for every Feature in that layer
354/// so we only have to store the properties and M-Value shape **once** per layer.
355pub fn encode_shape(shape: &Shape, cache: &mut ColumnCacheWriter) -> usize {
356    // this will store a "shape" of numbers on how to rebuild the object
357    let mut shape_store = Vec::<ColumnValue>::new();
358    // encode the shape data
359    shape.encode(&mut shape_store, cache);
360    // return the index of the shape index
361    cache.add_shapes(shape_store)
362}
363
364/// Decode shapes from the column cache using an index to find the shape encoding
365pub fn decode_shape(shape_index: usize, cache: &mut ColumnCacheReader) -> Shape {
366    let mut shape_store = cache.get_shapes(shape_index);
367    // duplicate the array to avoid modifying the original
368    Shape::decode(&mut shape_store, cache)
369}
370
371/// A shape pair for stronger compression and decoding
372#[derive(Debug, Clone, PartialEq)]
373pub struct ShapePair {
374    /// The type (0 - array, 1 - object, 2 - value)
375    pub p_type: ShapeDefinition,
376    /// the length if object or array; or the column to read from
377    pub count_or_col: usize,
378}
379impl ShapePair {
380    /// encode a shape pair
381    pub fn encode(p_type: ShapeDefinition, count_or_col: usize) -> usize {
382        (count_or_col << 2) + p_type as usize
383    }
384
385    /// decode a shape pair
386    pub fn decode(num: usize) -> ShapePair {
387        ShapePair { p_type: (num & 0b11).into(), count_or_col: num >> 2 }
388    }
389}
390impl From<usize> for ShapePair {
391    fn from(value: usize) -> Self {
392        ShapePair::decode(value)
393    }
394}
395
396/// The type of shape we are decoding
397#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
398pub enum ShapeDefinition {
399    /// an array
400    Array = 0,
401    /// an object
402    Object = 1,
403    /// a primitive
404    Primitive = 2,
405}
406impl From<usize> for ShapeDefinition {
407    fn from(value: usize) -> Self {
408        match value {
409            0 => ShapeDefinition::Array,
410            1 => ShapeDefinition::Object,
411            _ => ShapeDefinition::Primitive, // 2
412        }
413    }
414}
415
416//? VALUE
417
418/// Primitive types supported by Properties
419#[derive(Serialize, Default, Deserialize, Debug, Clone, PartialEq)]
420#[serde(untagged)]
421pub enum PrimitiveValue {
422    /// String type utf8 encoded
423    String(String),
424    /// unsigned 64 bit integer
425    U64(u64),
426    /// signed 64 bit integer
427    I64(i64),
428    /// floating point number
429    F32(f32),
430    /// double precision floating point number
431    F64(f64),
432    /// boolean
433    Bool(bool),
434    /// null
435    #[default]
436    Null,
437}
438impl PrimitiveValue {
439    fn encode(
440        &self,
441        shape: &PrimitiveShape,
442        store: &mut Vec<ColumnValue>,
443        cache: &mut ColumnCacheWriter,
444    ) {
445        match (self, shape) {
446            // string
447            (PrimitiveValue::String(s), PrimitiveShape::String) => {
448                store.push(cache.add_string(s.clone()).into())
449            }
450            // u64
451            (PrimitiveValue::U64(u), PrimitiveShape::U64) => store.push(cache.add_u64(*u).into()),
452            // i64
453            (PrimitiveValue::U64(u), PrimitiveShape::I64) => {
454                store.push(cache.add_i64(*u as i64).into())
455            }
456            (PrimitiveValue::I64(i), PrimitiveShape::I64) => store.push(cache.add_i64(*i).into()),
457            // f32
458            (PrimitiveValue::U64(u), PrimitiveShape::F32) => {
459                store.push(cache.add_f32(*u as f32).into())
460            }
461            (PrimitiveValue::I64(i), PrimitiveShape::F32) => {
462                store.push(cache.add_f32(*i as f32).into())
463            }
464            (PrimitiveValue::F32(f), PrimitiveShape::F32) => store.push(cache.add_f32(*f).into()),
465            // f64
466            (PrimitiveValue::U64(u), PrimitiveShape::F64) => {
467                store.push(cache.add_f64(*u as f64).into())
468            }
469            (PrimitiveValue::I64(i), PrimitiveShape::F64) => {
470                store.push(cache.add_f64(*i as f64).into())
471            }
472            (PrimitiveValue::F32(f), PrimitiveShape::F64) => {
473                store.push(cache.add_f64(*f as f64).into())
474            }
475            (PrimitiveValue::F64(f), PrimitiveShape::F64) => store.push(cache.add_f64(*f).into()),
476            // bool
477            (PrimitiveValue::Bool(b), PrimitiveShape::Bool) => {
478                store.push(cache.add_u64(if *b { 1 } else { 0 }).into())
479            }
480            // null
481            (PrimitiveValue::Null, PrimitiveShape::Null) => {}
482            #[tarpaulin::skip]
483            _ => panic!("shape mismatch"),
484        }
485    }
486
487    fn decode(
488        shape: &PrimitiveShape,
489        store: &mut Vec<usize>,
490        cache: &mut ColumnCacheReader,
491    ) -> Self {
492        let col_val = store.remove(0);
493        match shape {
494            PrimitiveShape::String => PrimitiveValue::String(cache.get_string(col_val)),
495            PrimitiveShape::U64 => PrimitiveValue::U64(cache.get_unsigned(col_val)),
496            PrimitiveShape::I64 => PrimitiveValue::I64(cache.get_signed(col_val)),
497            PrimitiveShape::F32 => PrimitiveValue::F32(cache.get_float(col_val)),
498            PrimitiveShape::F64 => PrimitiveValue::F64(cache.get_double(col_val)),
499            PrimitiveShape::Bool => PrimitiveValue::Bool(cache.get_unsigned(col_val) == 1),
500            PrimitiveShape::Null => {
501                // put the column back because null does not need to be decoded
502                store.insert(0, col_val);
503                PrimitiveValue::Null
504            }
505        }
506    }
507
508    fn default_from_shape(shape: &PrimitiveShape) -> Self {
509        match shape {
510            PrimitiveShape::String => PrimitiveValue::String(String::new()),
511            PrimitiveShape::U64 => PrimitiveValue::U64(0),
512            PrimitiveShape::I64 => PrimitiveValue::I64(0),
513            PrimitiveShape::F32 => PrimitiveValue::F32(0.0),
514            PrimitiveShape::F64 => PrimitiveValue::F64(0.0),
515            PrimitiveShape::Bool => PrimitiveValue::Bool(false),
516            PrimitiveShape::Null => PrimitiveValue::Null,
517        }
518    }
519
520    fn matching_shape(&self, other: &PrimitiveValue) -> bool {
521        matches!(
522            (self, other),
523            (PrimitiveValue::String(_), PrimitiveValue::String(_))
524                | (PrimitiveValue::U64(_), PrimitiveValue::U64(_))
525                | (PrimitiveValue::I64(_), PrimitiveValue::I64(_))
526                | (PrimitiveValue::F32(_), PrimitiveValue::F32(_))
527                | (PrimitiveValue::F64(_), PrimitiveValue::F64(_))
528                | (PrimitiveValue::Bool(_), PrimitiveValue::Bool(_))
529                | (PrimitiveValue::Null, PrimitiveValue::Null)
530        )
531    }
532}
533impl From<&MapboxValue> for PrimitiveValue {
534    fn from(mval: &MapboxValue) -> Self {
535        match mval {
536            MapboxValue::String(string) => PrimitiveValue::String(string.clone()),
537            MapboxValue::UInt(usigned) => PrimitiveValue::U64(*usigned),
538            MapboxValue::SInt(signed) => PrimitiveValue::I64(*signed),
539            MapboxValue::Float(float) => PrimitiveValue::F32(float.0),
540            MapboxValue::Double(double) => PrimitiveValue::F64(double.0),
541            MapboxValue::Bool(boolean) => PrimitiveValue::Bool(*boolean),
542            MapboxValue::Null => PrimitiveValue::Null,
543        }
544    }
545}
546impl From<PrimitiveValue> for MapboxValue {
547    fn from(val: PrimitiveValue) -> Self {
548        match val {
549            PrimitiveValue::String(string) => MapboxValue::String(string),
550            PrimitiveValue::U64(usigned) => MapboxValue::UInt(usigned),
551            PrimitiveValue::I64(signed) => MapboxValue::SInt(signed),
552            PrimitiveValue::F32(float) => MapboxValue::Float(CustomOrdWrapper(float)),
553            PrimitiveValue::F64(double) => MapboxValue::Double(CustomOrdWrapper(double)),
554            PrimitiveValue::Bool(boolean) => MapboxValue::Bool(boolean),
555            PrimitiveValue::Null => MapboxValue::Null,
556        }
557    }
558}
559
560/// Arrays may contain either a primitive or an object whose values are primitives
561#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
562#[serde(untagged)]
563pub enum ValuePrimitiveType {
564    /// Primitive type
565    Primitive(PrimitiveValue),
566    /// Nested shape that can only contain primitives
567    NestedPrimitive(BTreeMap<String, PrimitiveValue>),
568}
569impl ValuePrimitiveType {
570    fn encode(
571        &self,
572        shape: &ShapePrimitiveType,
573        store: &mut Vec<ColumnValue>,
574        cache: &mut ColumnCacheWriter,
575    ) {
576        match (shape, self) {
577            (
578                ShapePrimitiveType::Primitive(shape_prim),
579                ValuePrimitiveType::Primitive(value_prim),
580            ) => {
581                value_prim.encode(shape_prim, store, cache);
582            }
583            (
584                ShapePrimitiveType::NestedPrimitive(shape_nest),
585                ValuePrimitiveType::NestedPrimitive(value_nest),
586            ) => {
587                for (key, prim_shape) in shape_nest {
588                    let val = value_nest.get(key).unwrap();
589                    val.encode(prim_shape, store, cache);
590                }
591            }
592            #[tarpaulin::skip]
593            _ => panic!("shape and value do not match"),
594        }
595    }
596
597    fn decode(
598        shape: &ShapePrimitiveType,
599        store: &mut Vec<usize>,
600        cache: &mut ColumnCacheReader,
601    ) -> Self {
602        match shape {
603            ShapePrimitiveType::Primitive(shape_prim) => {
604                ValuePrimitiveType::Primitive(PrimitiveValue::decode(shape_prim, store, cache))
605            }
606            ShapePrimitiveType::NestedPrimitive(shape_nest) => ValuePrimitiveType::NestedPrimitive(
607                shape_nest
608                    .iter()
609                    .map(|(key, shape)| (key.clone(), PrimitiveValue::decode(shape, store, cache)))
610                    .collect(),
611            ),
612        }
613    }
614
615    fn same_nested(&self, nested: &BTreeMap<String, PrimitiveValue>) -> bool {
616        match self {
617            ValuePrimitiveType::Primitive(_) => false,
618            ValuePrimitiveType::NestedPrimitive(val) => {
619                for (key, val) in val {
620                    if !val.matching_shape(nested.get(key).unwrap()) {
621                        return false;
622                    }
623                }
624                true
625            }
626        }
627    }
628}
629
630/// Supports primitive types `string`, `number`, `boolean`, `null`
631/// May be an array of those types, or an object of those types
632/// Object keys are always strings, values can be any basic type, an array, or a nested object.
633/// Array values must all be the same type.
634#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
635#[serde(untagged)]
636pub enum ValueType {
637    /// A primitive value
638    Primitive(PrimitiveValue),
639    /// An array of values
640    Array(Vec<ValuePrimitiveType>),
641    /// A nested object
642    Nested(Value),
643}
644impl ValueType {
645    fn encode(
646        &self,
647        shape: &ShapeType,
648        store: &mut Vec<ColumnValue>,
649        cache: &mut ColumnCacheWriter,
650    ) {
651        match (self, shape) {
652            (ValueType::Primitive(val), ShapeType::Primitive(shape)) => {
653                val.encode(shape, store, cache);
654            }
655            (ValueType::Array(vals), ShapeType::Array(shape)) => {
656                // encode length
657                store.push(ColumnValue::Number(vals.len()));
658                for val in vals {
659                    val.encode(&shape[0], store, cache);
660                }
661            }
662            (ValueType::Nested(val), ShapeType::Nested(shape)) => {
663                val.encode(shape, store, cache);
664            }
665            #[tarpaulin::skip]
666            _ => panic!("shape and value do not match"),
667        }
668    }
669
670    fn decode(shape: &ShapeType, store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self {
671        match shape {
672            ShapeType::Primitive(shape_prim) => {
673                ValueType::Primitive(PrimitiveValue::decode(shape_prim, store, cache))
674            }
675            ShapeType::Array(shape_arr) => {
676                let mut val = Vec::<ValuePrimitiveType>::new();
677                let len = store.remove(0);
678                for _ in 0..len {
679                    val.push(ValuePrimitiveType::decode(&shape_arr[0], store, cache));
680                }
681                ValueType::Array(val)
682            }
683            ShapeType::Nested(shape) => ValueType::Nested(Value::decode(shape, store, cache)),
684        }
685    }
686
687    fn default_from_shape(shape: &ShapeType) -> Self {
688        match shape {
689            ShapeType::Primitive(shape) => {
690                ValueType::Primitive(PrimitiveValue::default_from_shape(shape))
691            }
692            ShapeType::Array(_) => ValueType::Array(vec![]),
693            ShapeType::Nested(shape) => ValueType::Nested(Value::default_from_shape(shape)),
694        }
695    }
696}
697impl From<&MapboxValue> for ValueType {
698    fn from(mval: &MapboxValue) -> Self {
699        ValueType::Primitive(mval.into())
700    }
701}
702impl From<ValueType> for MapboxValue {
703    fn from(val: ValueType) -> Self {
704        match val {
705            ValueType::Primitive(val) => val.into(),
706            #[tarpaulin::skip] // this isn't relevant
707            _ => MapboxValue::Null,
708        }
709    }
710}
711
712/// Value design
713#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq)]
714pub struct Value(pub BTreeMap<String, ValueType>);
715impl Value {
716    /// Encode the value into the store
717    pub fn encode(
718        &self,
719        shape: &Shape,
720        store: &mut Vec<ColumnValue>,
721        cache: &mut ColumnCacheWriter,
722    ) {
723        for (key, shape_type) in &shape.0 {
724            let val = self.0.get(key).unwrap_or(&ValueType::default_from_shape(shape_type)).clone();
725            val.encode(shape_type, store, cache);
726        }
727    }
728
729    /// Decode the value from the store
730    pub fn decode(shape: &Shape, store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self {
731        let mut value = BTreeMap::new();
732        for (key, shape_type) in &shape.0 {
733            let val = ValueType::decode(shape_type, store, cache);
734            value.insert(key.clone(), val);
735        }
736        Value(value)
737    }
738
739    fn default_from_shape(shape: &Shape) -> Self {
740        let mut value = BTreeMap::new();
741        for (key, shape_type) in &shape.0 {
742            value.insert(key.clone(), ValueType::default_from_shape(shape_type));
743        }
744        Value(value)
745    }
746}
747impl From<&MapboxProperties> for Value {
748    fn from(mval: &MapboxProperties) -> Self {
749        let mut value = BTreeMap::new();
750        for (key, val) in mval {
751            value.insert(key.clone(), val.into());
752        }
753        Value(value)
754    }
755}
756impl From<Value> for MapboxProperties {
757    fn from(val: Value) -> Self {
758        let mut mval = BTreeMap::new();
759        for (key, val) in val.0 {
760            mval.insert(key, val.into());
761        }
762        mval
763    }
764}
765/// Value of a features properties object
766pub type Properties = Value;
767/// Value of a feature's M-Values object
768pub type MValue = Value;
769
770/// Encode a value to the column cache
771pub fn encode_value(value: &Value, shape: &Shape, cache: &mut ColumnCacheWriter) -> usize {
772    let mut value_store: Vec<ColumnValue> = vec![];
773    value.encode(shape, &mut value_store, cache);
774    cache.add_shapes(value_store)
775}
776
777/// Decode a value from the column cache
778pub fn decode_value(value_index: usize, shape: &Shape, cache: &mut ColumnCacheReader) -> Value {
779    let value_store = cache.get_shapes(value_index);
780    Value::decode(shape, &mut value_store.clone(), cache)
781}
782
783/// LineString Properties Value
784pub type LineStringMValues = Vec<MValue>;
785/// MultiLineString MValues Value
786pub type MultiLineStringMValues = Vec<LineStringMValues>;
787/// Polygon MValues Value
788pub type PolygonMValues = Vec<LineStringMValues>;
789/// MultiPolygon MValues Value
790pub type MultiPolygonMValues = Vec<PolygonMValues>;
791
792/// All possible M-Value shapes
793#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
794#[serde(untagged)]
795pub enum MValues {
796    /// Single M-Value
797    MValue(MValue),
798    /// LineString M-Value
799    LineStringMValues(LineStringMValues),
800    /// MultiLineString M-Value
801    MultiLineStringMValues(MultiLineStringMValues),
802    /// Polygon M-Value
803    PolygonMValues(PolygonMValues),
804    /// MultiPolygon M-Value
805    MultiPolygonMValues(MultiPolygonMValues),
806}
807
808//? The Following are utility functions when the user doesn't pre-define the Properties/M-Value
809//? Shapes to store:
810
811/// This is primarily to check if the type is a primitive.
812/// If the primitive is a number, find the "depth", the most complex is f64, then i64, then u64.
813/// Otherwise, if the primitives don't match, throw an error.
814/// If the type is NOT a primitive, ensure that all types in the array match
815/// returns - a single type from the list to validate the correct type to be parsed from values later
816pub fn validate_types(types: &[ValuePrimitiveType]) -> ShapePrimitiveType {
817    match types.first() {
818        Some(ValuePrimitiveType::Primitive(primitive)) => {
819            let mut base: PrimitiveShape = primitive.clone().into();
820            let is_number = base.is_number();
821            for t in types {
822                match t {
823                    ValuePrimitiveType::Primitive(t_prim) => {
824                        let prim_shape = t_prim.clone().into();
825                        if !base.matching_shape(&prim_shape) {
826                            panic!("All types must be the same");
827                        } else if is_number {
828                            base = PrimitiveShape::get_highest_order_number(&base, &prim_shape);
829                        }
830                        // otherwise do nothing
831                    }
832                    #[tarpaulin::skip]
833                    _ => panic!("All types must be the same"),
834                }
835            }
836
837            ShapePrimitiveType::Primitive(base)
838        }
839        Some(ValuePrimitiveType::NestedPrimitive(nested)) => {
840            // iterate and check if each following types match
841            for t in types[1..].iter() {
842                if !t.same_nested(nested) {
843                    panic!("All types must be the same");
844                }
845            }
846
847            ValuePrimitiveType::NestedPrimitive(nested.clone()).into()
848        }
849        None => ShapePrimitiveType::Primitive(PrimitiveShape::Null),
850    }
851}