use crate::{
BBoxQuantization, CustomOrdWrapper, Point, Point3D, VectorPoints, VectorPoints3D,
delta_decode_array, delta_encode_array, unweave_and_delta_decode_3d_array,
unweave_and_delta_decode_array, weave_and_delta_encode_3d_array, weave_and_delta_encode_array,
};
use alloc::{collections::BTreeMap, string::String, vec::Vec};
use core::cell::RefCell;
use pbf::{ProtoRead, ProtoWrite, Protobuf};
use s2json::BBOX;
#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub enum OColumnName {
#[default]
String = 1,
Unsigned = 2,
Signed = 3,
Float = 4,
Double = 5,
Points = 6,
Points3D = 7,
Indices = 8,
Shapes = 9,
BBox = 10,
}
impl From<u64> for OColumnName {
fn from(value: u64) -> Self {
match value {
1 => OColumnName::String,
2 => OColumnName::Unsigned,
3 => OColumnName::Signed,
4 => OColumnName::Float,
5 => OColumnName::Double,
6 => OColumnName::Points,
7 => OColumnName::Points3D,
8 => OColumnName::Indices,
9 => OColumnName::Shapes,
10 => OColumnName::BBox,
_ => OColumnName::String,
}
}
}
impl From<OColumnName> for u64 {
fn from(col: OColumnName) -> Self {
col as u64
}
}
#[derive(Debug)]
pub enum ColumnContainer<T> {
Pos(usize),
Data(T),
}
#[derive(Debug, Default)]
pub struct ColumnCacheReader {
string: Vec<String>,
unsigned: Vec<u64>,
signed: Vec<i64>,
float: Vec<f32>,
double: Vec<f64>,
points: Vec<VectorPoints>,
points_3d: Vec<VectorPoints3D>,
indices: Vec<Vec<u32>>,
shapes: Vec<Vec<usize>>,
bbox: Vec<BBOX>,
}
impl ColumnCacheReader {
pub fn new() -> Self {
ColumnCacheReader { ..Default::default() }
}
pub fn get_string(&mut self, index: usize) -> String {
self.string[index].clone()
}
pub fn get_unsigned(&self, index: usize) -> u64 {
self.unsigned[index]
}
pub fn get_signed(&self, index: usize) -> i64 {
self.signed[index]
}
pub fn get_float(&self, index: usize) -> f32 {
self.float[index]
}
pub fn get_double(&self, index: usize) -> f64 {
self.double[index]
}
pub fn get_points(&mut self, index: usize) -> VectorPoints {
self.points[index].clone()
}
pub fn get_points_3d(&mut self, index: usize) -> VectorPoints3D {
self.points_3d[index].clone()
}
pub fn get_indices(&mut self, index: usize) -> Vec<u32> {
self.indices[index].clone()
}
pub fn get_shapes(&mut self, index: usize) -> Vec<usize> {
self.shapes[index].clone()
}
pub fn get_bbox(&mut self, index: usize) -> BBOX {
self.bbox[index]
}
}
impl ProtoRead for ColumnCacheReader {
fn read(&mut self, tag: u64, pb: &mut Protobuf) {
let col: OColumnName = tag.into();
match col {
OColumnName::String => self.string.push(pb.read_string()),
OColumnName::Unsigned => self.unsigned.push(pb.read_varint::<u64>()),
OColumnName::Signed => self.signed.push(pb.read_s_varint::<i64>()),
OColumnName::Float => self.float.push(pb.read_varint::<f32>()),
OColumnName::Double => self.double.push(pb.read_varint::<f64>()),
OColumnName::Points => {
self.points.push(unweave_and_delta_decode_array(&pb.read_packed::<u64>()))
}
OColumnName::Points3D => {
self.points_3d.push(unweave_and_delta_decode_3d_array(&pb.read_packed::<u64>()))
}
OColumnName::Indices => self.indices.push(delta_decode_array(&pb.read_packed::<u32>())),
OColumnName::Shapes => self.shapes.push(pb.read_packed::<usize>()),
OColumnName::BBox => self.bbox.push(BBOX::dequantize(&pb.read_packed::<u8>()[..])),
}
}
}
#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct OColumnBaseChunk {
pub index: usize,
pub count: usize,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub enum ColumnValue {
Number(usize),
Column(RefCell<OColumnBaseChunk>),
}
impl From<usize> for ColumnValue {
fn from(index: usize) -> Self {
ColumnValue::Number(index)
}
}
impl From<RefCell<OColumnBaseChunk>> for ColumnValue {
fn from(chunk: RefCell<OColumnBaseChunk>) -> Self {
ColumnValue::Column(chunk)
}
}
pub type OColumnBaseWrite<K> = BTreeMap<K, RefCell<OColumnBaseChunk>>;
pub type OColumnBaseFloatWrite<K> = BTreeMap<CustomOrdWrapper<K>, RefCell<OColumnBaseChunk>>;
#[derive(Debug, Default)]
pub struct ColumnCacheWriter {
string: OColumnBaseWrite<String>,
unsigned: OColumnBaseWrite<u64>,
signed: OColumnBaseWrite<i64>,
float: OColumnBaseFloatWrite<f32>,
double: OColumnBaseFloatWrite<f64>,
points: OColumnBaseWrite<Vec<Point>>,
points_3d: OColumnBaseWrite<Vec<Point3D>>,
indices: OColumnBaseWrite<Vec<u32>>,
shapes: OColumnBaseWrite<Vec<ColumnValue>>,
bbox: OColumnBaseWrite<BBOX>,
}
impl ColumnCacheWriter {
pub fn add_string(&mut self, value: String) -> usize {
add(&mut self.string, value)
}
pub fn add_u64(&mut self, value: u64) -> RefCell<OColumnBaseChunk> {
add_number(&mut self.unsigned, value)
}
pub fn add_i64(&mut self, value: i64) -> RefCell<OColumnBaseChunk> {
add_number(&mut self.signed, value)
}
pub fn add_f32(&mut self, value: f32) -> RefCell<OColumnBaseChunk> {
add_number(&mut self.float, CustomOrdWrapper(value))
}
pub fn add_f64(&mut self, value: f64) -> RefCell<OColumnBaseChunk> {
add_number(&mut self.double, CustomOrdWrapper(value))
}
pub fn add_points(&mut self, value: Vec<Point>) -> usize {
add(&mut self.points, value)
}
pub fn add_points_3d(&mut self, value: Vec<Point3D>) -> usize {
add(&mut self.points_3d, value)
}
pub fn add_indices(&mut self, value: Vec<u32>) -> usize {
add(&mut self.indices, value)
}
pub fn add_shapes(&mut self, value: Vec<ColumnValue>) -> usize {
add(&mut self.shapes, value)
}
pub fn add_bbox(&mut self, value: BBOX) -> usize {
add(&mut self.bbox, value)
}
}
impl ProtoWrite for ColumnCacheWriter {
fn write(&self, pbf: &mut Protobuf) {
let mut strings: Vec<(&String, &RefCell<OColumnBaseChunk>)> = self.string.iter().collect();
let mut unsigned: Vec<(&u64, &RefCell<OColumnBaseChunk>)> = self.unsigned.iter().collect();
let mut signed: Vec<(&i64, &RefCell<OColumnBaseChunk>)> = self.signed.iter().collect();
let mut float: Vec<(&CustomOrdWrapper<f32>, &RefCell<OColumnBaseChunk>)> =
self.float.iter().collect();
let mut double: Vec<(&CustomOrdWrapper<f64>, &RefCell<OColumnBaseChunk>)> =
self.double.iter().collect();
let mut points: Vec<(&Vec<Point>, &RefCell<OColumnBaseChunk>)> =
self.points.iter().collect();
let mut points_3d: Vec<(&Vec<Point3D>, &RefCell<OColumnBaseChunk>)> =
self.points_3d.iter().collect();
let mut indices: Vec<(&Vec<u32>, &RefCell<OColumnBaseChunk>)> =
self.indices.iter().collect();
let mut shapes: Vec<(&Vec<ColumnValue>, &RefCell<OColumnBaseChunk>)> =
self.shapes.iter().collect();
let mut bbox: Vec<(&BBOX, &RefCell<OColumnBaseChunk>)> = self.bbox.iter().collect();
strings.sort_by(|a, b| a.1.borrow().index.cmp(&b.1.borrow().index));
unsigned.sort_by(|a, b| a.1.borrow().index.cmp(&b.1.borrow().index));
signed.sort_by(|a, b| a.1.borrow().index.cmp(&b.1.borrow().index));
float.sort_by(|a, b| a.1.borrow().index.cmp(&b.1.borrow().index));
double.sort_by(|a, b| a.1.borrow().index.cmp(&b.1.borrow().index));
points.sort_by(|a, b| a.1.borrow().index.cmp(&b.1.borrow().index));
points_3d.sort_by(|a, b| a.1.borrow().index.cmp(&b.1.borrow().index));
indices.sort_by(|a, b| a.1.borrow().index.cmp(&b.1.borrow().index));
shapes.sort_by(|a, b| a.1.borrow().index.cmp(&b.1.borrow().index));
bbox.sort_by(|a, b| a.1.borrow().index.cmp(&b.1.borrow().index));
for string in strings {
pbf.write_string_field(OColumnName::String.into(), string.0);
}
for u in unsigned {
pbf.write_varint_field(OColumnName::Unsigned.into(), *u.0);
}
for s in signed {
pbf.write_s_varint_field(OColumnName::Signed.into(), *s.0);
}
for f in float {
pbf.write_varint_field(OColumnName::Float.into(), f.0.0);
}
for d in double {
pbf.write_varint_field(OColumnName::Double.into(), d.0.0);
}
for p in points {
pbf.write_packed_varint(OColumnName::Points.into(), &weave_and_delta_encode_array(p.0));
}
for p_3d in points_3d {
pbf.write_packed_varint(
OColumnName::Points3D.into(),
&weave_and_delta_encode_3d_array(p_3d.0),
);
}
for i in indices {
pbf.write_packed_varint(OColumnName::Indices.into(), &delta_encode_array(i.0));
}
for s in shapes {
let packed: Vec<usize> =
s.0.iter()
.map(|v| match v {
ColumnValue::Number(n) => *n,
ColumnValue::Column(c) => c.borrow().index,
})
.collect();
pbf.write_packed_varint(OColumnName::Shapes.into(), &packed);
}
for bbox in bbox {
pbf.write_packed_varint(OColumnName::BBox.into(), &bbox.0.quantize());
}
}
}
pub fn add<T>(col: &mut OColumnBaseWrite<T>, value: T) -> usize
where
T: Ord,
{
if let Some(col) = col.get_mut(&value) {
let mut chunk = col.borrow_mut();
chunk.count += 1;
chunk.index
} else {
let index = col.len();
col.insert(value, RefCell::new(OColumnBaseChunk { index, count: 1 }));
index
}
}
pub fn add_number<T>(col: &mut OColumnBaseWrite<T>, value: T) -> RefCell<OColumnBaseChunk>
where
T: Ord,
{
if let Some(chunk) = col.get_mut(&value) {
{
let mut chunk_mut = chunk.borrow_mut();
chunk_mut.count += 1;
}
chunk.clone()
} else {
let index = col.len();
let new_chunk = RefCell::new(OColumnBaseChunk { index, count: 1 });
col.insert(value, new_chunk.clone());
new_chunk
}
}