Skip to main content

interstice_abi/interstice_value/convert/
tuple.rs

1#![allow(non_snake_case)]
2
3use crate::{IntersticeAbiError, IntersticeValue};
4
5#[allow(non_snake_case)]
6macro_rules! impl_tuple_into_interstice {
7    ( $( $name:ident ),+ ) => {
8        impl<$( $name ),+> From<( $( $name ),+ )> for IntersticeValue
9        where
10            $( $name: Into<IntersticeValue> ),+
11        {
12            fn from(value: ( $( $name ),+ )) -> Self {
13                let ( $( $name ),+ ) = value;
14                IntersticeValue::Tuple(vec![
15                    $( $name.into() ),+
16                ])
17            }
18        }
19    };
20}
21
22impl_tuple_into_interstice!(A, B);
23impl_tuple_into_interstice!(A, B, C);
24impl_tuple_into_interstice!(A, B, C, D);
25impl_tuple_into_interstice!(A, B, C, D, E);
26impl_tuple_into_interstice!(A, B, C, D, E, F);
27impl_tuple_into_interstice!(A, B, C, D, E, F, G);
28impl_tuple_into_interstice!(A, B, C, D, E, F, G, H);
29
30macro_rules! count_idents {
31    ($($idents:ident),*) => {
32        <[()]>::len(&[$(count_idents!(@sub $idents)),*])
33    };
34    (@sub $ident:ident) => { () };
35}
36
37macro_rules! impl_tuple_tryfrom_interstice {
38    ( $( $name:ident ),+ ) => {
39        impl<$( $name ),+> TryFrom<IntersticeValue> for ( $( $name ),+ )
40        where
41            $( $name: TryFrom<IntersticeValue> ),+,
42        {
43            type Error = IntersticeAbiError;
44
45            fn try_from(value: IntersticeValue) -> Result<Self, Self::Error> {
46                match value {
47                    IntersticeValue::Tuple(vec) => {
48                        let expected = count_idents!( $( $name ),+ );
49                        if vec.len() != expected {
50                            return Err(IntersticeAbiError::ConversionError(format!(
51                                "Tuple arity mismatch: expected {}, got {}",
52                                expected,
53                                vec.len()
54                            )));
55                        }
56
57                        // We index instead of consuming iterator so order is explicit
58                        let mut iter = vec.into_iter();
59                        Ok((
60                            $(
61                                {
62                                    let v = iter.next().unwrap();
63                                    <$name  as TryFrom<IntersticeValue>>::try_from(v).map_err(|_err| {IntersticeAbiError::ConversionError(format!("Couldn't convert inner tuple value"))})?
64                                }
65                            ),+
66                        ))
67                    }
68                    other => Err(IntersticeAbiError::ConversionError(format!("Expected Tuple, got {:?}", other))),
69                }
70            }
71        }
72    };
73}
74
75impl_tuple_tryfrom_interstice!(A, B);
76impl_tuple_tryfrom_interstice!(A, B, C);
77impl_tuple_tryfrom_interstice!(A, B, C, D);
78impl_tuple_tryfrom_interstice!(A, B, C, D, E);
79impl_tuple_tryfrom_interstice!(A, B, C, D, E, F);
80impl_tuple_tryfrom_interstice!(A, B, C, D, E, F, G);
81impl_tuple_tryfrom_interstice!(A, B, C, D, E, F, G, H);