use tokio::io::AsyncReadExt;
use crate::{Result, io::ClickhouseRead, values::Value};
use super::{Deserializer, DeserializerState, Type};
pub trait ArrayDeserializerGeneric {
type Item;
fn inner_type(type_: &Type) -> &Type;
fn inner_value(items: Vec<Self::Item>) -> Value;
fn item_mapping(value: Value) -> Self::Item;
}
pub struct ArrayDeserializer;
impl ArrayDeserializerGeneric for ArrayDeserializer {
type Item = Value;
fn inner_type(type_: &Type) -> &Type {
type_.unwrap_array()
}
fn inner_value(items: Vec<Self::Item>) -> Value {
Value::Array(items)
}
fn item_mapping(value: Value) -> Value {
value
}
}
impl<T: ArrayDeserializerGeneric + 'static> Deserializer for T {
async fn read_prefix<R: ClickhouseRead>(
type_: &Type,
reader: &mut R,
state: &mut DeserializerState,
) -> Result<()> {
Self::inner_type(type_)
.deserialize_prefix(reader, state)
.await
}
async fn read<R: ClickhouseRead>(
type_: &Type,
reader: &mut R,
rows: usize,
state: &mut DeserializerState,
) -> Result<Vec<Value>> {
if rows == 0 {
return Ok(vec![]);
}
let mut offsets = vec![];
for _ in 0..rows {
offsets.push(reader.read_u64_le().await?);
}
let mut items = Self::inner_type(type_)
.deserialize_column(reader, offsets[offsets.len() - 1] as usize, state)
.await?
.into_iter()
.map(Self::item_mapping);
let mut out = Vec::with_capacity(rows);
let mut read_offset = 0u64;
for offset in offsets {
let len = offset - read_offset;
read_offset = offset;
out.push(Self::inner_value((&mut items).take(len as usize).collect()));
}
Ok(out)
}
}