use crate::de::IDLDeserialize;
use crate::ser::IDLBuilder;
use crate::{check_prog, pretty_check_file, pretty_parse, types::Type, TypeEnv};
use crate::{CandidType, Error, Result};
use serde::de::Deserialize;
use std::path::Path;
pub enum CandidSource<'a> {
File(&'a Path),
Text(&'a str),
}
impl<'a> CandidSource<'a> {
pub fn load(&self) -> Result<(TypeEnv, Option<Type>)> {
Ok(match self {
CandidSource::File(path) => pretty_check_file(path)?,
CandidSource::Text(str) => {
let ast = pretty_parse("", str)?;
let mut env = TypeEnv::new();
let actor = check_prog(&mut env, &ast)?;
(env, actor)
}
})
}
}
pub fn service_compatible(new: CandidSource, old: CandidSource) -> Result<()> {
let (mut env, t1) = new.load()?;
let t1 = t1.ok_or_else(|| Error::msg("new interface has no main service type"))?;
let (env2, t2) = old.load()?;
let t2 = t2.ok_or_else(|| Error::msg("old interface has no main service type"))?;
let mut gamma = std::collections::HashSet::new();
let t2 = env.merge_type(env2, t2);
crate::types::subtype::subtype(&mut gamma, &env, &t1, &t2)?;
Ok(())
}
#[macro_export]
macro_rules! Encode {
( $($x:expr),* ) => {{
let mut builder = $crate::ser::IDLBuilder::new();
Encode!(@PutValue builder $($x,)*)
}};
( @PutValue $builder:ident $x:expr, $($tail:expr,)* ) => {{
$builder.arg($x).and_then(|builder| Encode!(@PutValue builder $($tail,)*))
}};
( @PutValue $builder:ident ) => {{
$builder.serialize_to_vec()
}};
}
#[macro_export]
macro_rules! Decode {
( $hex:expr $(,$ty:ty)* ) => {{
$crate::de::IDLDeserialize::new($hex)
.and_then(|mut de| Decode!(@GetValue [] de $($ty,)*)
.and_then(|res| de.done().and(Ok(res))))
}};
(@GetValue [$($ans:ident)*] $de:ident $ty:ty, $($tail:ty,)* ) => {{
$de.get_value::<$ty>()
.and_then(|val| Decode!(@GetValue [$($ans)* val] $de $($tail,)* ))
}};
(@GetValue [$($ans:ident)*] $de:ident) => {{
Ok(($($ans),*))
}};
}
pub fn decode_args<'a, Tuple>(bytes: &'a [u8]) -> Result<Tuple>
where
Tuple: ArgumentDecoder<'a>,
{
let mut de = IDLDeserialize::new(bytes)?;
let res = ArgumentDecoder::decode(&mut de)?;
de.done()?;
Ok(res)
}
pub fn decode_one<'a, T>(bytes: &'a [u8]) -> Result<T>
where
T: Deserialize<'a> + CandidType,
{
let (res,) = decode_args(bytes)?;
Ok(res)
}
pub fn write_args<Tuple: ArgumentEncoder, Writer: std::io::Write>(
writer: &mut Writer,
arguments: Tuple,
) -> Result<()> {
let mut ser = IDLBuilder::new();
arguments.encode(&mut ser)?;
ser.serialize(writer)
}
pub fn encode_args<Tuple: ArgumentEncoder>(arguments: Tuple) -> Result<Vec<u8>> {
let mut result = Vec::new();
write_args(&mut result, arguments)?;
Ok(result)
}
pub fn encode_one<T: CandidType>(argument: T) -> Result<Vec<u8>> {
encode_args((argument,))
}
pub trait ArgumentDecoder<'a>: Sized {
fn decode(de: &mut IDLDeserialize<'a>) -> Result<Self>;
}
impl<'a> ArgumentDecoder<'a> for () {
fn decode(_de: &mut IDLDeserialize<'a>) -> Result<()> {
Ok(())
}
}
pub trait ArgumentEncoder {
fn encode(self, ser: &mut IDLBuilder) -> Result<()>;
}
impl ArgumentEncoder for () {
fn encode(self, _de: &mut IDLBuilder) -> Result<()> {
Ok(())
}
}
macro_rules! decode_impl {
( $($id: ident : $typename: ident),* ) => {
impl<'a, $( $typename ),*> ArgumentDecoder<'a> for ($($typename,)*)
where
$( $typename: Deserialize<'a> + CandidType ),*
{
fn decode(de: &mut IDLDeserialize<'a>) -> Result<Self> {
$(
let $id: $typename = de.get_value()?;
)*
Ok(($( $id, )*))
}
}
}
}
macro_rules! encode_impl {
( $($id: ident : $typename: ident),* ) => {
impl<$( $typename ),*> ArgumentEncoder for ($($typename,)*)
where
$( $typename: CandidType ),*
{
fn encode(self, ser: &mut IDLBuilder) -> Result<()> {
let ( $( $id, )* ) = self;
$(
ser.arg(&$id)?;
)*
Ok(())
}
}
}
}
decode_impl!(a: A);
decode_impl!(a: A, b: B);
decode_impl!(a: A, b: B, c: C);
decode_impl!(a: A, b: B, c: C, d: D);
decode_impl!(a: A, b: B, c: C, d: D, e: E);
decode_impl!(a: A, b: B, c: C, d: D, e: E, f: F);
decode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
decode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
decode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
decode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
#[rustfmt::skip]
decode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K);
#[rustfmt::skip]
decode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L);
#[rustfmt::skip]
decode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M);
#[rustfmt::skip]
decode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N);
#[rustfmt::skip]
decode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O);
#[rustfmt::skip]
decode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O, p: P);
encode_impl!(a: A);
encode_impl!(a: A, b: B);
encode_impl!(a: A, b: B, c: C);
encode_impl!(a: A, b: B, c: C, d: D);
encode_impl!(a: A, b: B, c: C, d: D, e: E);
encode_impl!(a: A, b: B, c: C, d: D, e: E, f: F);
encode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
encode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
encode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
encode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
#[rustfmt::skip]
encode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K);
#[rustfmt::skip]
encode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L);
#[rustfmt::skip]
encode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M);
#[rustfmt::skip]
encode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N);
#[rustfmt::skip]
encode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O);
#[rustfmt::skip]
encode_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L, m: M, n: N, o: O, p: P);