use crate::{
def::{ProcedureDef, ReducerDef, ViewDef},
identifier::Identifier,
};
use spacetimedb_lib::{
sats::{self, de, impl_serialize, ser, ProductValue},
ProductType,
};
pub struct ArgsSeed<'a, Def>(pub sats::WithTypespace<'a, Def>);
impl<Def> Clone for ArgsSeed<'_, Def> {
fn clone(&self) -> Self {
*self
}
}
impl<Def> Copy for ArgsSeed<'_, Def> {}
pub trait FunctionDef {
fn params(&self) -> &ProductType;
fn name(&self) -> &Identifier;
}
impl FunctionDef for ReducerDef {
fn params(&self) -> &ProductType {
&self.params
}
fn name(&self) -> &Identifier {
self.name.as_identifier()
}
}
impl FunctionDef for ProcedureDef {
fn params(&self) -> &ProductType {
&self.params
}
fn name(&self) -> &Identifier {
&self.name
}
}
impl FunctionDef for ViewDef {
fn params(&self) -> &ProductType {
&self.params
}
fn name(&self) -> &Identifier {
&self.name
}
}
impl<Def: FunctionDef> ArgsSeed<'_, Def> {
pub fn name(&self) -> &Identifier {
self.0.ty().name()
}
pub fn params(&self) -> &ProductType {
self.0.ty().params()
}
}
impl<'de, Def: FunctionDef> de::DeserializeSeed<'de> for ArgsSeed<'_, Def> {
type Output = ProductValue;
fn deserialize<D: de::Deserializer<'de>>(self, deserializer: D) -> Result<Self::Output, D::Error> {
deserializer.deserialize_product(self)
}
}
impl<'de, Def: FunctionDef> de::ProductVisitor<'de> for ArgsSeed<'_, Def> {
type Output = ProductValue;
fn product_name(&self) -> Option<&str> {
Some(self.0.ty().name())
}
fn product_len(&self) -> usize {
self.0.ty().params().elements.len()
}
fn product_kind(&self) -> de::ProductKind {
de::ProductKind::ReducerArgs
}
fn visit_seq_product<A: de::SeqProductAccess<'de>>(self, tup: A) -> Result<Self::Output, A::Error> {
de::visit_seq_product(self.0.map(|r| &*r.params().elements), &self, tup)
}
fn visit_named_product<A: de::NamedProductAccess<'de>>(self, tup: A) -> Result<Self::Output, A::Error> {
de::visit_named_product(self.0.map(|r| &*r.params().elements), &self, tup)
}
}
pub struct ReducerArgsWithSchema<'a> {
value: &'a ProductValue,
ty: sats::WithTypespace<'a, ReducerDef>,
}
impl_serialize!([] ReducerArgsWithSchema<'_>, (self, ser) => {
use itertools::Itertools;
use ser::SerializeSeqProduct;
let mut seq = ser.serialize_seq_product(self.value.elements.len())?;
for (value, elem) in self.value.elements.iter().zip_eq(&*self.ty.ty().params.elements) {
seq.serialize_element(&self.ty.with(&elem.algebraic_type).with_value(value))?;
}
seq.end()
});