Skip to main content

topcoat_runtime/
arguments.rs

1use serde::{Deserialize, Deserializer, Serialize, Serializer};
2
3/// A tuple of call arguments encoded as a JSON array.
4///
5/// An empty argument list is `[]`, while a single unit argument is `[null]`.
6/// Each argument keeps its own serialization, including surrogate values.
7#[derive(Debug)]
8pub struct Arguments<T>(pub T);
9
10impl Serialize for Arguments<()> {
11    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
12        [(); 0].serialize(serializer)
13    }
14}
15
16impl<'de> Deserialize<'de> for Arguments<()> {
17    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
18        <[(); 0]>::deserialize(deserializer)?;
19        Ok(Self(()))
20    }
21}
22
23macro_rules! impl_arguments {
24    ($($t:ident),+ $(,)?) => {
25        impl<$($t: Serialize),+> Serialize for Arguments<($($t,)+)> {
26            fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
27                self.0.serialize(serializer)
28            }
29        }
30
31        impl<'de, $($t: Deserialize<'de>),+> Deserialize<'de> for Arguments<($($t,)+)> {
32            fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
33                <($($t,)+)>::deserialize(deserializer).map(Self)
34            }
35        }
36    };
37}
38
39impl_arguments!(T1);
40impl_arguments!(T1, T2);
41impl_arguments!(T1, T2, T3);
42impl_arguments!(T1, T2, T3, T4);
43impl_arguments!(T1, T2, T3, T4, T5);
44impl_arguments!(T1, T2, T3, T4, T5, T6);
45impl_arguments!(T1, T2, T3, T4, T5, T6, T7);
46impl_arguments!(T1, T2, T3, T4, T5, T6, T7, T8);
47impl_arguments!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
48impl_arguments!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
49impl_arguments!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
50impl_arguments!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
51
52#[cfg(test)]
53mod tests {
54    use serde_json::{from_str, to_string};
55
56    use super::*;
57    use crate::{Surrogate, Surrogated};
58
59    #[test]
60    fn empty_arguments_and_one_unit_argument_have_distinct_encodings() {
61        assert_eq!(to_string(&Arguments(())).unwrap(), "[]");
62        assert_eq!(to_string(&Arguments(((),))).unwrap(), "[null]");
63        from_str::<Arguments<()>>("[]").unwrap();
64        from_str::<Arguments<((),)>>("[null]").unwrap();
65        assert_eq!(to_string(&()).unwrap(), "null");
66    }
67
68    #[test]
69    fn arguments_require_an_array_of_the_declared_length() {
70        for input in ["null", "{}", "[null]", "[true]"] {
71            assert!(from_str::<Arguments<()>>(input).is_err(), "{input}");
72        }
73        for input in ["null", "true", "[]", "[true, false]", "[1]"] {
74            assert!(from_str::<Arguments<(bool,)>>(input).is_err(), "{input}");
75        }
76    }
77
78    #[test]
79    fn arguments_preserve_each_values_surrogate_encoding() {
80        let value = (42u128, Some(String::from("hello")));
81        let arguments = Arguments(value.clone().into_surrogate());
82        let json = to_string(&arguments).unwrap();
83        assert_eq!(
84            json,
85            r#"[{"t":"u128","bits":128,"v":"42"},{"t":"Option","v":"hello"}]"#,
86        );
87        let decoded: Arguments<<(u128, Option<String>) as Surrogated>::Surrogate> =
88            from_str(&json).unwrap();
89        assert_eq!(decoded.0.into_real(), value);
90    }
91}