use crate::{ Error, FheProgramInputTrait, InnerPlaintext, NumCiphertexts, Params, Plaintext, Result, TryFromPlaintext, TryIntoPlaintext, Type, TypeName, TypeNameInstance, WithContext, }; use seal_fhe::Plaintext as SealPlaintext; impl TryIntoPlaintext for [T; N] where T: TryIntoPlaintext, Self: TypeName, { fn try_into_plaintext(&self, params: &Params) -> Result { let element_plaintexts = self .iter() .map(|v| v.try_into_plaintext(params)) .collect::<Result<Vec<Plaintext>>>()? .drain(0..) .flat_map(|p| match p.inner { InnerPlaintext::Seal(v) => v, }) .collect::<Vec<WithContext<SealPlaintext>>>(); Ok(Plaintext { inner: InnerPlaintext::Seal(element_plaintexts), data_type: Self::type_name(), }) } } impl<T, const N: usize> TryFromPlaintext for [T; N] where T: TryFromPlaintext + TypeName + NumCiphertexts, Self: TypeName + NumCiphertexts, { fn try_from_plaintext(plaintext: &Plaintext, params: &Params) -> Result<Self> { let data = match &plaintext.inner { InnerPlaintext::Seal(p) => { if p.len() != Self::NUM_CIPHERTEXTS { return Err(Error::MalformedPlaintext); } p.chunks(T::NUM_CIPHERTEXTS) .map(|c| { let p = Plaintext { data_type: T::type_name(), inner: InnerPlaintext::Seal(c.to_owned()), }; T::try_from_plaintext(&p, params) }) .collect::<Result<Vec<T>>>()? } }; Ok(match data.try_into() { Ok(v) => v, _ => unreachable!(), }) } } impl<T, const N: usize> TypeName for [T; N] where T: TypeName, { fn type_name() -> Type { let inner_type = T::type_name(); Type { name: format!("[{};{}]", inner_type.name, N), ..inner_type } } } impl<T, const N: usize> TypeNameInstance for [T; N] where T: TypeName, { fn type_name_instance(&self) -> Type { Self::type_name() } } impl<T, const N: usize> FheProgramInputTrait for [T; N] where T: TypeName + TryIntoPlaintext {} impl<T, const N: usize> NumCiphertexts for [T; N] where T: NumCiphertexts, { const NUM_CIPHERTEXTS: usize = T::NUM_CIPHERTEXTS * N; }