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