open_vector_tile/open/
shape.rs

1use crate::open::{ColumnCacheReader, ColumnCacheWriter, ColumnValue};
2use alloc::{vec, vec::Vec};
3use s2json::{
4    PrimitiveShape, PrimitiveShapeType, PrimitiveValue, Shape, ShapePrimitive, ShapeType, Value,
5    ValuePrimitive, ValuePrimitiveType, ValueType,
6};
7use serde::{Deserialize, Serialize};
8
9//? Shape
10
11// Shapes exist solely to deconstruct and rebuild objects.
12//
13// Shape limitations:
14// - all keys are strings.
15// - all values are either:
16// - - primitive types: strings, numbers (f32, f64, u64, i64), true, false, or null
17// - - sub types: an array of a shape or a nested object which is itself a shape
18// - - if the sub type is an array, ensure all elements are of the same type
19// The interfaces below help describe how shapes are built by the user.
20
21trait PrimitiveShapeToStore {
22    fn encode(&self, shape_store: &mut Vec<ColumnValue>, cache: &mut ColumnCacheWriter);
23    fn decode(shape_store: &mut Vec<usize>) -> Self;
24}
25impl PrimitiveShapeToStore for PrimitiveShape {
26    fn encode(&self, shape_store: &mut Vec<ColumnValue>, _cache: &mut ColumnCacheWriter) {
27        shape_store.push(ShapePair::encode(ShapeDefinition::Primitive, self.into()).into());
28    }
29
30    fn decode(shape_store: &mut Vec<usize>) -> Self {
31        let shape_pair = ShapePair::decode(shape_store.remove(0));
32        shape_pair.count_or_col.into()
33    }
34}
35
36trait ShapePrimitiveTypeToStore {
37    fn encode(&self, shape_store: &mut Vec<ColumnValue>, cache: &mut ColumnCacheWriter);
38    fn decode(store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self;
39}
40impl ShapePrimitiveTypeToStore for PrimitiveShapeType {
41    fn encode(&self, shape_store: &mut Vec<ColumnValue>, cache: &mut ColumnCacheWriter) {
42        match self {
43            Self::Primitive(prim) => prim.encode(shape_store, cache),
44            Self::NestedPrimitive(nested) => {
45                shape_store.push(ShapePair::encode(ShapeDefinition::Object, nested.len()).into());
46                for (key, value) in nested.iter() {
47                    shape_store.push(cache.add_string(key.clone()).into());
48                    value.encode(shape_store, cache);
49                }
50            }
51        }
52    }
53
54    fn decode(store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self {
55        let shape_pair = ShapePair::decode(store.remove(0));
56        match shape_pair.p_type {
57            ShapeDefinition::Primitive => {
58                Self::Primitive(PrimitiveShape::from(shape_pair.count_or_col))
59            }
60            ShapeDefinition::Object => {
61                let mut nested = ShapePrimitive::new();
62                for _ in 0..shape_pair.count_or_col {
63                    nested.insert(cache.get_string(store.remove(0)), PrimitiveShape::decode(store));
64                }
65                Self::NestedPrimitive(nested)
66            }
67            #[tarpaulin::skip]
68            _ => panic!("Unknown shape definition: {:?}", shape_pair),
69        }
70    }
71}
72
73trait ShapeTypeToStore {
74    fn encode(&self, shape_store: &mut Vec<ColumnValue>, cache: &mut ColumnCacheWriter);
75    fn decode(store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self;
76}
77impl ShapeTypeToStore for ShapeType {
78    fn encode(&self, shape_store: &mut Vec<ColumnValue>, cache: &mut ColumnCacheWriter) {
79        match self {
80            Self::Primitive(prim) => prim.encode(shape_store, cache),
81            Self::Array(array) => {
82                shape_store.push(0.into());
83                array.first().unwrap().encode(shape_store, cache);
84            }
85            Self::Nested(nested) => {
86                nested.encode(shape_store, cache);
87            }
88        }
89    }
90
91    fn decode(store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self {
92        let code = store.remove(0);
93        let shape_pair = ShapePair::decode(code);
94        match shape_pair.p_type {
95            ShapeDefinition::Primitive => {
96                Self::Primitive(PrimitiveShape::from(shape_pair.count_or_col))
97            }
98            ShapeDefinition::Array => Self::Array(vec![PrimitiveShapeType::decode(store, cache)]),
99            ShapeDefinition::Object => {
100                // reinsert code because shape will check it again
101                store.insert(0, code);
102                Self::Nested(Shape::decode(store, cache))
103            }
104        }
105    }
106}
107
108/// Encode/Decode a Shape to the column cache
109pub trait ShapeToStore {
110    /// Encode the shape
111    fn encode(&self, shape_store: &mut Vec<ColumnValue>, cache: &mut ColumnCacheWriter);
112    /// Decode the shape
113    fn decode(store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self;
114}
115impl ShapeToStore for Shape {
116    fn encode(&self, shape_store: &mut Vec<ColumnValue>, cache: &mut ColumnCacheWriter) {
117        shape_store.push(ShapePair::encode(ShapeDefinition::Object, self.len()).into());
118        for (key, value) in self.iter() {
119            shape_store.push(cache.add_string(key.clone()).into());
120            value.encode(shape_store, cache);
121        }
122    }
123    fn decode(store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self {
124        let mut map = Shape::new();
125        let shape_pair = ShapePair::decode(store.remove(0));
126        if shape_pair.p_type != ShapeDefinition::Object {
127            panic!("expected object shape")
128        }
129        for _ in 0..shape_pair.count_or_col {
130            let key = cache.get_string(store.remove(0));
131            let shape = ShapeType::decode(store, cache);
132            map.insert(key, shape);
133        }
134        map
135    }
136}
137
138/// Create shapes
139///
140/// Used by Layer's and Feature's M-Values
141/// Must be an object of key values
142/// all keys will be the same, values will be different
143/// A layer's Shape defines what the properties look like for every Feature in that layer
144/// so we only have to store the properties and M-Value shape **once** per layer.
145pub fn encode_shape(shape: &Shape, cache: &mut ColumnCacheWriter) -> usize {
146    // this will store a "shape" of numbers on how to rebuild the object
147    let mut shape_store = Vec::<ColumnValue>::new();
148    // encode the shape data
149    shape.encode(&mut shape_store, cache);
150    // return the index of the shape index
151    cache.add_shapes(shape_store)
152}
153
154/// Decode shapes from the column cache using an index to find the shape encoding
155pub fn decode_shape(shape_index: usize, cache: &mut ColumnCacheReader) -> Shape {
156    let mut shape_store = cache.get_shapes(shape_index);
157    // duplicate the array to avoid modifying the original
158    Shape::decode(&mut shape_store, cache)
159}
160
161/// A shape pair for stronger compression and decoding
162#[derive(Debug, Clone, PartialEq)]
163pub struct ShapePair {
164    /// The type (0 - array, 1 - object, 2 - value)
165    pub p_type: ShapeDefinition,
166    /// the length if object or array; or the column to read from
167    pub count_or_col: usize,
168}
169impl ShapePair {
170    /// encode a shape pair
171    pub fn encode(p_type: ShapeDefinition, count_or_col: usize) -> usize {
172        (count_or_col << 2) + p_type as usize
173    }
174
175    /// decode a shape pair
176    pub fn decode(num: usize) -> ShapePair {
177        ShapePair { p_type: (num & 0b11).into(), count_or_col: num >> 2 }
178    }
179}
180impl From<usize> for ShapePair {
181    fn from(value: usize) -> Self {
182        ShapePair::decode(value)
183    }
184}
185
186/// The type of shape we are decoding
187#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
188pub enum ShapeDefinition {
189    /// an array
190    Array = 0,
191    /// an object
192    Object = 1,
193    /// a primitive
194    Primitive = 2,
195}
196impl From<usize> for ShapeDefinition {
197    fn from(value: usize) -> Self {
198        match value {
199            0 => ShapeDefinition::Array,
200            1 => ShapeDefinition::Object,
201            _ => ShapeDefinition::Primitive, // 2
202        }
203    }
204}
205
206trait PrimitiveValueToStore {
207    fn encode(
208        &self,
209        shape: &PrimitiveShape,
210        store: &mut Vec<ColumnValue>,
211        cache: &mut ColumnCacheWriter,
212    );
213    fn decode(
214        shape: &PrimitiveShape,
215        store: &mut Vec<usize>,
216        cache: &mut ColumnCacheReader,
217    ) -> Self;
218}
219impl PrimitiveValueToStore for PrimitiveValue {
220    fn encode(
221        &self,
222        shape: &PrimitiveShape,
223        store: &mut Vec<ColumnValue>,
224        cache: &mut ColumnCacheWriter,
225    ) {
226        match (self, shape) {
227            // string
228            (PrimitiveValue::String(s), PrimitiveShape::String) => {
229                store.push(cache.add_string(s.clone()).into())
230            }
231            // u64
232            (PrimitiveValue::U64(u), PrimitiveShape::U64) => store.push(cache.add_u64(*u).into()),
233            // i64
234            (PrimitiveValue::U64(u), PrimitiveShape::I64) => {
235                store.push(cache.add_i64(*u as i64).into())
236            }
237            (PrimitiveValue::I64(i), PrimitiveShape::I64) => store.push(cache.add_i64(*i).into()),
238            // f32
239            (PrimitiveValue::U64(u), PrimitiveShape::F32) => {
240                store.push(cache.add_f32(*u as f32).into())
241            }
242            (PrimitiveValue::I64(i), PrimitiveShape::F32) => {
243                store.push(cache.add_f32(*i as f32).into())
244            }
245            (PrimitiveValue::F32(f), PrimitiveShape::F32) => store.push(cache.add_f32(*f).into()),
246            // f64
247            (PrimitiveValue::U64(u), PrimitiveShape::F64) => {
248                store.push(cache.add_f64(*u as f64).into())
249            }
250            (PrimitiveValue::I64(i), PrimitiveShape::F64) => {
251                store.push(cache.add_f64(*i as f64).into())
252            }
253            (PrimitiveValue::F32(f), PrimitiveShape::F64) => {
254                store.push(cache.add_f64(*f as f64).into())
255            }
256            (PrimitiveValue::F64(f), PrimitiveShape::F64) => store.push(cache.add_f64(*f).into()),
257            // bool
258            (PrimitiveValue::Bool(b), PrimitiveShape::Bool) => {
259                store.push(cache.add_u64(if *b { 1 } else { 0 }).into())
260            }
261            // null
262            (PrimitiveValue::Null, PrimitiveShape::Null) => {}
263            #[tarpaulin::skip]
264            _ => panic!("shape mismatch"),
265        }
266    }
267
268    fn decode(
269        shape: &PrimitiveShape,
270        store: &mut Vec<usize>,
271        cache: &mut ColumnCacheReader,
272    ) -> Self {
273        let col_val = store.remove(0);
274        match shape {
275            PrimitiveShape::String => PrimitiveValue::String(cache.get_string(col_val)),
276            PrimitiveShape::U64 => PrimitiveValue::U64(cache.get_unsigned(col_val)),
277            PrimitiveShape::I64 => PrimitiveValue::I64(cache.get_signed(col_val)),
278            PrimitiveShape::F32 => PrimitiveValue::F32(cache.get_float(col_val)),
279            PrimitiveShape::F64 => PrimitiveValue::F64(cache.get_double(col_val)),
280            PrimitiveShape::Bool => PrimitiveValue::Bool(cache.get_unsigned(col_val) == 1),
281            PrimitiveShape::Null => {
282                // put the column back because null does not need to be decoded
283                store.insert(0, col_val);
284                PrimitiveValue::Null
285            }
286        }
287    }
288}
289
290trait PrimitiveShapeTypeToStore {
291    fn encode(
292        &self,
293        shape: &PrimitiveShapeType,
294        store: &mut Vec<ColumnValue>,
295        cache: &mut ColumnCacheWriter,
296    );
297    fn decode(
298        shape: &PrimitiveShapeType,
299        store: &mut Vec<usize>,
300        cache: &mut ColumnCacheReader,
301    ) -> Self;
302}
303impl PrimitiveShapeTypeToStore for ValuePrimitiveType {
304    fn encode(
305        &self,
306        shape: &PrimitiveShapeType,
307        store: &mut Vec<ColumnValue>,
308        cache: &mut ColumnCacheWriter,
309    ) {
310        match (shape, self) {
311            (
312                PrimitiveShapeType::Primitive(shape_prim),
313                ValuePrimitiveType::Primitive(value_prim),
314            ) => {
315                value_prim.encode(shape_prim, store, cache);
316            }
317            (
318                PrimitiveShapeType::NestedPrimitive(shape_nest),
319                ValuePrimitiveType::NestedPrimitive(value_nest),
320            ) => {
321                for (key, prim_shape) in shape_nest.iter() {
322                    let val = value_nest.get(key).unwrap();
323                    val.encode(prim_shape, store, cache);
324                }
325            }
326            #[tarpaulin::skip]
327            _ => panic!("shape and value do not match"),
328        }
329    }
330    fn decode(
331        shape: &PrimitiveShapeType,
332        store: &mut Vec<usize>,
333        cache: &mut ColumnCacheReader,
334    ) -> Self {
335        match shape {
336            PrimitiveShapeType::Primitive(shape_prim) => {
337                ValuePrimitiveType::Primitive(PrimitiveValue::decode(shape_prim, store, cache))
338            }
339            PrimitiveShapeType::NestedPrimitive(shape_nest) => {
340                let mut map = ValuePrimitive::new();
341                for (key, shape) in shape_nest.iter() {
342                    map.insert(key.clone(), PrimitiveValue::decode(shape, store, cache));
343                }
344                ValuePrimitiveType::NestedPrimitive(map)
345            }
346        }
347    }
348}
349
350/// Encode/Decode a ValueType to the column cache with a Shape describing how to store
351pub trait ValueTypeToStore {
352    /// Encode the value type into the store
353    fn encode(
354        &self,
355        shape: &ShapeType,
356        store: &mut Vec<ColumnValue>,
357        cache: &mut ColumnCacheWriter,
358    );
359    /// Decode the value type from the store
360    fn decode(shape: &ShapeType, store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self;
361}
362impl ValueTypeToStore for ValueType {
363    fn encode(
364        &self,
365        shape: &ShapeType,
366        store: &mut Vec<ColumnValue>,
367        cache: &mut ColumnCacheWriter,
368    ) {
369        match (self, shape) {
370            (ValueType::Primitive(val), ShapeType::Primitive(shape)) => {
371                val.encode(shape, store, cache);
372            }
373            (ValueType::Array(vals), ShapeType::Array(shape)) => {
374                // encode length
375                store.push(ColumnValue::Number(vals.len()));
376                for val in vals {
377                    val.encode(&shape[0], store, cache);
378                }
379            }
380            (ValueType::Nested(val), ShapeType::Nested(shape)) => {
381                val.encode(shape, store, cache);
382            }
383            #[tarpaulin::skip]
384            _ => panic!("shape and value do not match"),
385        }
386    }
387
388    fn decode(shape: &ShapeType, store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self {
389        match shape {
390            ShapeType::Primitive(shape_prim) => {
391                ValueType::Primitive(PrimitiveValue::decode(shape_prim, store, cache))
392            }
393            ShapeType::Array(shape_arr) => {
394                let mut val = Vec::<ValuePrimitiveType>::new();
395                let len = store.remove(0);
396                for _ in 0..len {
397                    val.push(ValuePrimitiveType::decode(&shape_arr[0], store, cache));
398                }
399                ValueType::Array(val)
400            }
401            ShapeType::Nested(shape) => ValueType::Nested(Value::decode(shape, store, cache)),
402        }
403    }
404}
405
406/// Encode/Decode a Value to the column cache with a Shape describing how to store
407pub trait ValueToStore {
408    /// Encode the value into the store
409    fn encode(&self, shape: &Shape, store: &mut Vec<ColumnValue>, cache: &mut ColumnCacheWriter);
410    /// Decode the value from the store
411    fn decode(shape: &Shape, store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self;
412}
413impl ValueToStore for Value {
414    fn encode(&self, shape: &Shape, store: &mut Vec<ColumnValue>, cache: &mut ColumnCacheWriter) {
415        for (key, shape_type) in shape.iter() {
416            let val = self.get(key).unwrap_or(&ValueType::default_from_shape(shape_type)).clone();
417            val.encode(shape_type, store, cache);
418        }
419    }
420    fn decode(shape: &Shape, store: &mut Vec<usize>, cache: &mut ColumnCacheReader) -> Self {
421        let mut value = Self::new();
422        for (key, shape_type) in shape.iter() {
423            let val = ValueType::decode(shape_type, store, cache);
424            value.insert(key.clone(), val);
425        }
426        value
427    }
428}
429
430/// Encode a value to the column cache
431pub fn encode_value(value: &Value, shape: &Shape, cache: &mut ColumnCacheWriter) -> usize {
432    let mut value_store: Vec<ColumnValue> = vec![];
433    value.encode(shape, &mut value_store, cache);
434    cache.add_shapes(value_store)
435}
436
437/// Decode a value from the column cache
438pub fn decode_value(value_index: usize, shape: &Shape, cache: &mut ColumnCacheReader) -> Value {
439    let value_store = cache.get_shapes(value_index);
440    Value::decode(shape, &mut value_store.clone(), cache)
441}