#[cfg(feature = "introspection")]
use crate::introspection::{ir, DynIntrospectable, Introspectable, LexicalId, References};
use crate::tags::{PrimaryTag, Tag};
use crate::{Deserialize, DeserializeError, Deserializer, Serialize, SerializeError, Serializer};
macro_rules! impl_tuple {
{ $len:literal, $( ($tag:ident, $gen:ident, $idx:tt) ),+ } => {
impl<$( $tag: Tag ),+> Tag for ($( $tag ,)+) { }
impl<$( $tag: PrimaryTag ),+> PrimaryTag for ($( $tag ,)+) {
type Tag = ($( $tag::Tag ,)+);
}
impl<$( $tag, $gen ),+> Serialize<($( $tag ,)+)> for ($( $gen ,)+)
where
$(
$tag: Tag,
$gen: Serialize<$tag>,
)+
{
fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
let mut serializer = serializer.serialize_struct2()?;
$(
serializer.serialize($idx as u32, self.$idx)?;
)+
serializer.finish()
}
}
impl<$( $tag, $gen ),+> Deserialize<($( $tag ,)+)> for ($( $gen ,)+)
where
$(
$tag: Tag,
$gen: Deserialize<$tag>,
)+
{
fn deserialize(deserializer: Deserializer) -> Result<Self, DeserializeError> {
let mut deserializer = deserializer.deserialize_struct()?;
$(
#[allow(non_snake_case)]
let mut $gen = None;
)+
while let Some(deserializer) = deserializer.deserialize()? {
match deserializer.id() {
$( $idx => $gen = deserializer.deserialize().map(Some)?, )+
_ => return Err(DeserializeError::InvalidSerialization),
}
}
deserializer.finish_with(|_| {
Ok(($( $gen.ok_or(DeserializeError::InvalidSerialization)?, )+))
})
}
}
impl<'a, $( $tag, $gen ),+> Serialize<($( $tag ,)+)> for &'a ($( $gen ,)+)
where
$(
$tag: Tag,
&'a $gen: Serialize<$tag>,
)+
{
fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
let mut serializer = serializer.serialize_struct2()?;
$(
serializer.serialize($idx as u32, &self.$idx)?;
)+
serializer.finish()
}
}
#[cfg(feature = "introspection")]
impl<$( $gen ),+> Introspectable for ($( $gen, )+)
where
$( $gen: Introspectable ),+
{
fn layout() -> ir::LayoutIr {
ir::StructIr::builder("std", concat!("Tuple", $len))
$(
.field(
ir::FieldIr::builder(
$idx,
concat!("field", $idx),
true,
$gen::lexical_id(),
)
.finish(),
)
)+
.finish()
.into()
}
fn lexical_id() -> LexicalId {
LexicalId::custom_generic(
"std",
concat!("Tuple", $len),
&[$( $gen::lexical_id() ),+],
)
}
fn add_references(references: &mut References) {
let types: [DynIntrospectable; $len] = [
$( DynIntrospectable::new::<$gen>() ),+
];
references.extend(types);
}
}
};
}
impl_tuple! { 1, (T0, U0, 0) }
impl_tuple! { 2, (T0, U0, 0), (T1, U1, 1) }
impl_tuple! { 3, (T0, U0, 0), (T1, U1, 1), (T2, U2, 2) }
impl_tuple! { 4, (T0, U0, 0), (T1, U1, 1), (T2, U2, 2), (T3, U3, 3) }
impl_tuple! { 5, (T0, U0, 0), (T1, U1, 1), (T2, U2, 2), (T3, U3, 3), (T4, U4, 4) }
impl_tuple! { 6, (T0, U0, 0), (T1, U1, 1), (T2, U2, 2), (T3, U3, 3), (T4, U4, 4), (T5, U5, 5) }
impl_tuple! {
7,
(T0, U0, 0), (T1, U1, 1), (T2, U2, 2), (T3, U3, 3), (T4, U4, 4), (T5, U5, 5), (T6, U6, 6)
}
impl_tuple! {
8,
(T0, U0, 0), (T1, U1, 1), (T2, U2, 2), (T3, U3, 3), (T4, U4, 4), (T5, U5, 5), (T6, U6, 6),
(T7, U7, 7)
}
impl_tuple! {
9,
(T0, U0, 0), (T1, U1, 1), (T2, U2, 2), (T3, U3, 3), (T4, U4, 4), (T5, U5, 5), (T6, U6, 6),
(T7, U7, 7), (T8, U8, 8)
}
impl_tuple! {
10,
(T0, U0, 0), (T1, U1, 1), (T2, U2, 2), (T3, U3, 3), (T4, U4, 4), (T5, U5, 5), (T6, U6, 6),
(T7, U7, 7), (T8, U8, 8), (T9, U9, 9)
}
impl_tuple! {
11,
(T0, U0, 0), (T1, U1, 1), (T2, U2, 2), (T3, U3, 3), (T4, U4, 4), (T5, U5, 5), (T6, U6, 6),
(T7, U7, 7), (T8, U8, 8), (T9, U9, 9), (T10, U10, 10)
}
impl_tuple! {
12,
(T0, U0, 0), (T1, U1, 1), (T2, U2, 2), (T3, U3, 3), (T4, U4, 4), (T5, U5, 5), (T6, U6, 6),
(T7, U7, 7), (T8, U8, 8), (T9, U9, 9), (T10, U10, 10), (T11, U11, 11)
}