use serde::{Deserialize, Serialize};
use super::{CustomValidator, PolyFuncTypeRV, SignatureFunc};
#[derive(serde::Deserialize, serde::Serialize, PartialEq, Debug, Clone)]
struct SerSignatureFunc {
signature: Option<PolyFuncTypeRV>,
binary: bool,
}
pub(super) fn serialize<S>(value: &super::SignatureFunc, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match value {
SignatureFunc::PolyFuncType(poly) => SerSignatureFunc {
signature: Some(poly.clone()),
binary: false,
},
SignatureFunc::CustomValidator(CustomValidator { poly_func, .. })
| SignatureFunc::MissingValidateFunc(poly_func) => SerSignatureFunc {
signature: Some(poly_func.clone()),
binary: true,
},
SignatureFunc::CustomFunc(_) | SignatureFunc::MissingComputeFunc => SerSignatureFunc {
signature: None,
binary: true,
},
}
.serialize(serializer)
}
pub(super) fn deserialize<'de, D>(deserializer: D) -> Result<super::SignatureFunc, D::Error>
where
D: serde::Deserializer<'de>,
{
let SerSignatureFunc { signature, binary } = SerSignatureFunc::deserialize(deserializer)?;
match (signature, binary) {
(Some(sig), false) => Ok(sig.into()),
(Some(sig), true) => Ok(SignatureFunc::MissingValidateFunc(sig)),
(None, true) => Ok(SignatureFunc::MissingComputeFunc),
(None, false) => Err(serde::de::Error::custom(
"No signature provided and custom computation not expected.",
)),
}
}
#[cfg(test)]
mod test {
use cool_asserts::assert_matches;
use serde::de::Error;
use super::*;
use crate::{
extension::{
CustomSignatureFunc, CustomValidator, OpDef, SignatureError, ValidateTypeArgs,
prelude::usize_t,
},
types::{FuncValueType, Signature, TypeArg},
};
#[derive(serde::Deserialize, serde::Serialize, Debug)]
struct Wrapper {
#[serde(
serialize_with = "serialize",
deserialize_with = "deserialize",
flatten
)]
inner: SignatureFunc,
}
impl TryFrom<SerSignatureFunc> for SignatureFunc {
type Error = serde_json::Error;
fn try_from(value: SerSignatureFunc) -> Result<Self, Self::Error> {
let ser = serde_json::to_value(value).unwrap();
let w: Wrapper = serde_json::from_value(ser)?;
Ok(w.inner)
}
}
impl From<SignatureFunc> for SerSignatureFunc {
fn from(value: SignatureFunc) -> Self {
let ser = serde_json::to_value(Wrapper { inner: value }).unwrap();
serde_json::from_value(ser).unwrap()
}
}
struct CustomSig;
impl CustomSignatureFunc for CustomSig {
fn compute_signature<'o, 'a: 'o>(
&'a self,
_arg_values: &[TypeArg],
_def: &'o crate::extension::op_def::OpDef,
) -> Result<crate::types::PolyFuncTypeRV, crate::extension::SignatureError> {
Ok(Default::default())
}
fn static_params(&self) -> &[crate::types::type_param::TypeParam] {
&[]
}
}
struct NoValidate;
impl ValidateTypeArgs for NoValidate {
fn validate<'o, 'a: 'o>(
&self,
_arg_values: &[TypeArg],
_def: &'o OpDef,
) -> Result<(), SignatureError> {
Ok(())
}
}
#[test]
fn test_serial_sig_func() {
let sig: FuncValueType = Signature::new_endo([usize_t()]).into();
let simple: SignatureFunc = sig.clone().into();
let ser: SerSignatureFunc = simple.into();
let expected_ser = SerSignatureFunc {
signature: Some(sig.clone().into()),
binary: false,
};
assert_eq!(ser, expected_ser);
let deser = SignatureFunc::try_from(ser).unwrap();
assert_matches!( deser,
SignatureFunc::PolyFuncType(poly_func) => {
assert_eq!(poly_func, sig.clone().into());
});
let with_custom: SignatureFunc = CustomValidator::new(sig.clone(), NoValidate).into();
let ser: SerSignatureFunc = with_custom.into();
let expected_ser = SerSignatureFunc {
signature: Some(sig.clone().into()),
binary: true,
};
assert_eq!(ser, expected_ser);
let mut deser = SignatureFunc::try_from(ser.clone()).unwrap();
assert_matches!(&deser,
SignatureFunc::MissingValidateFunc(poly_func) => {
assert_eq!(poly_func, &PolyFuncTypeRV::from(sig.clone()));
}
);
assert_eq!(
SerSignatureFunc::from(SignatureFunc::try_from(ser).unwrap()),
expected_ser
);
deser.ignore_missing_validation();
assert_matches!(&deser, &SignatureFunc::PolyFuncType(_));
let custom: SignatureFunc = CustomSig.into();
let ser: SerSignatureFunc = custom.into();
let expected_ser = SerSignatureFunc {
signature: None,
binary: true,
};
assert_eq!(ser, expected_ser);
let deser = SignatureFunc::try_from(ser).unwrap();
assert_matches!(&deser, &SignatureFunc::MissingComputeFunc);
assert_eq!(SerSignatureFunc::from(deser), expected_ser);
let bad_ser = SerSignatureFunc {
signature: None,
binary: false,
};
let err = SignatureFunc::try_from(bad_ser).unwrap_err();
assert_eq!(
err.to_string(),
serde_json::Error::custom("No signature provided and custom computation not expected.")
.to_string()
);
}
}