Files
Sunscreen/sunscreen_runtime/src/array.rs
2022-05-16 16:09:07 -07:00

93 lines
2.5 KiB
Rust

use crate::{
Error, FheProgramInputTrait, InnerPlaintext, NumCiphertexts, Params, Plaintext, Result,
TryFromPlaintext, TryIntoPlaintext, Type, TypeName, TypeNameInstance, WithContext,
};
use seal_fhe::Plaintext as SealPlaintext;
impl<T, const N: usize> TryIntoPlaintext for [T; N]
where
T: TryIntoPlaintext,
Self: TypeName,
{
fn try_into_plaintext(&self, params: &Params) -> Result<Plaintext> {
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;
}