use super::unexpected_type;
use crate::{Error, FromSql, Result, ToSql, Type, Value};
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct VecTuple<T>(pub Vec<T>);
impl<T: ToSql> ToSql for VecTuple<T> {
fn to_sql(self, type_hint: Option<&Type>) -> Result<Value> {
Ok(Value::Tuple(
self.0
.into_iter()
.enumerate()
.map(|(i, x)| x.to_sql(type_hint.and_then(|x| x.untuple()?.get(i))))
.collect::<Result<Vec<_>>>()?,
))
}
}
impl<T: FromSql> FromSql for VecTuple<T> {
fn from_sql(type_: &Type, value: Value) -> Result<Self> {
let subtype = match type_ {
Type::Tuple(x) => &**x,
x => return Err(unexpected_type(x)),
};
let Value::Tuple(values) = value else { return Err(unexpected_type(type_)) };
if values.len() != subtype.len() {
return Err(Error::DeserializeError(format!(
"unexpected type: mismatch tuple length expected {}, got {}",
subtype.len(),
values.len()
)));
}
let mut out = Vec::with_capacity(values.len());
for (type_, value) in subtype.iter().zip(values.into_iter()) {
out.push(T::from_sql(type_, value)?);
}
Ok(VecTuple(out))
}
}