klickhouse 0.15.2

Klickhouse is a pure Rust SDK for working with Clickhouse with the native protocol in async environments with minimal boilerplate and maximal performance.
Documentation
use crate::{Result, io::ClickhouseRead, values::Value};

use super::{Deserializer, DeserializerState, Type};

use crate::values;

pub struct PointDeserializer;

impl Deserializer for PointDeserializer {
    async fn read_prefix<R: ClickhouseRead>(
        _type_: &Type,
        reader: &mut R,
        state: &mut DeserializerState,
    ) -> Result<()> {
        for _ in 0..2 {
            Type::Float64.deserialize_prefix(reader, state).await?;
        }
        Ok(())
    }

    async fn read<R: ClickhouseRead>(
        _type_: &Type,
        reader: &mut R,
        rows: usize,
        state: &mut DeserializerState,
    ) -> Result<Vec<Value>> {
        let mut points = vec![Value::Point(Default::default()); rows];
        for col in 0..2 {
            for (row, value) in Type::Float64
                .deserialize_column(reader, rows, state)
                .await?
                .into_iter()
                .enumerate()
            {
                let Value::Float64(value) = value else {
                    unreachable!()
                };
                match &mut points[row] {
                    Value::Point(point) => point.0[col] = value,
                    _ => {
                        unreachable!()
                    }
                }
            }
        }
        Ok(points)
    }
}
macro_rules! array_deser {
    ($name:ident, $item:ty) => {
        paste::paste! {
            pub struct [<$name Deserializer>];
            impl super::array::ArrayDeserializerGeneric for [<$name Deserializer>] {
                type Item = crate::values::$item;
                fn inner_type(_type_: &Type) -> &Type {
                    &Type::$item
                }
                fn inner_value(items: Vec<Self::Item>) -> Value {
                    Value::$name(values::$name(items))
                }
                fn item_mapping(value: Value) -> Self::Item {
                    let Value::$item(point) = value else {
                        unreachable!()
                    };
                    point
                }
            }
        }
    };
}

array_deser!(Ring, Point);
array_deser!(Polygon, Ring);
array_deser!(MultiPolygon, Polygon);