Skip to main content

topcoat_runtime/surrogate/
tuple.rs

1use std::ops::Deref;
2
3use crate::{Surrogate, Surrogated};
4
5impl Surrogated for () {
6    type Surrogate = ();
7    fn into_surrogate(self) -> Self::Surrogate {}
8}
9
10impl Surrogate for () {
11    type Real = ();
12    fn into_real(self) -> Self::Real {}
13}
14
15/// A tuple whose elements can be borrowed as runtime values.
16pub trait TupleProject<'a> {
17    /// A tuple of the borrowed elements' surrogates.
18    type Projected;
19
20    fn project(&'a self) -> Self::Projected;
21}
22
23/// A borrowed tuple of runtime values.
24///
25/// Field access reads the borrowed elements, so `.0` on a borrowed pair
26/// borrows its first element.
27pub struct TupleRefSurrogate<'a, T>
28where
29    T: TupleProject<'a>,
30{
31    real: &'a T,
32    projected: T::Projected,
33}
34
35impl<'a, T> TupleRefSurrogate<'a, T>
36where
37    T: TupleProject<'a>,
38{
39    fn new(real: &'a T) -> Self {
40        Self {
41            real,
42            projected: real.project(),
43        }
44    }
45}
46
47impl<'a, T> TupleRefSurrogate<'a, T>
48where
49    T: TupleProject<'a> + Surrogated + Clone,
50{
51    /// Clones the borrowed tuple into an owned tuple.
52    // Cloning a `&(A, B)` yields an `(A, B)`, which `Clone` cannot express.
53    #[must_use]
54    #[allow(clippy::should_implement_trait)]
55    pub fn clone(&self) -> T::Surrogate {
56        self.real.clone().into_surrogate()
57    }
58}
59
60impl<'a, T> Deref for TupleRefSurrogate<'a, T>
61where
62    T: TupleProject<'a>,
63{
64    type Target = T::Projected;
65
66    fn deref(&self) -> &Self::Target {
67        &self.projected
68    }
69}
70
71impl<'a, T> serde::Serialize for TupleRefSurrogate<'a, T>
72where
73    T: TupleProject<'a>,
74    T::Projected: serde::Serialize,
75{
76    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
77    where
78        S: serde::Serializer,
79    {
80        self.projected.serialize(serializer)
81    }
82}
83
84macro_rules! impl_tuple_surrogate {
85    ($($t:ident $idx:tt),+ $(,)?) => {
86        impl<$($t),+> Surrogated for ($($t,)+)
87        where
88            $($t: Surrogated,)+
89        {
90            type Surrogate = ($(<$t as Surrogated>::Surrogate,)+);
91
92            fn into_surrogate(self) -> Self::Surrogate {
93                ($(self.$idx.into_surrogate(),)+)
94            }
95        }
96
97        impl<$($t),+> Surrogate for ($($t,)+)
98        where
99            $($t: Surrogate,)+
100        {
101            type Real = ($(<$t as Surrogate>::Real,)+);
102
103            fn into_real(self) -> Self::Real {
104                ($(self.$idx.into_real(),)+)
105            }
106        }
107
108        impl<'a, $($t: 'a),+> TupleProject<'a> for ($($t,)+)
109        where
110            $(&'a $t: Surrogated,)+
111        {
112            type Projected = ($(<&'a $t as Surrogated>::Surrogate,)+);
113
114            fn project(&'a self) -> Self::Projected {
115                ($((&self.$idx).into_surrogate(),)+)
116            }
117        }
118
119        impl<'a, $($t: 'a),+> Surrogated for &'a ($($t,)+)
120        where
121            $(&'a $t: Surrogated,)+
122        {
123            type Surrogate = TupleRefSurrogate<'a, ($($t,)+)>;
124
125            fn into_surrogate(self) -> Self::Surrogate {
126                TupleRefSurrogate::new(self)
127            }
128        }
129
130        impl<'a, $($t: 'a),+> Surrogate for TupleRefSurrogate<'a, ($($t,)+)>
131        where
132            $(&'a $t: Surrogated,)+
133        {
134            type Real = &'a ($($t,)+);
135
136            fn into_real(self) -> Self::Real {
137                self.real
138            }
139        }
140    };
141}
142
143impl_tuple_surrogate!(T1 0);
144impl_tuple_surrogate!(T1 0, T2 1);
145impl_tuple_surrogate!(T1 0, T2 1, T3 2);
146impl_tuple_surrogate!(T1 0, T2 1, T3 2, T4 3);
147impl_tuple_surrogate!(T1 0, T2 1, T3 2, T4 3, T5 4);
148impl_tuple_surrogate!(T1 0, T2 1, T3 2, T4 3, T5 4, T6 5);
149impl_tuple_surrogate!(T1 0, T2 1, T3 2, T4 3, T5 4, T6 5, T7 6);
150impl_tuple_surrogate!(T1 0, T2 1, T3 2, T4 3, T5 4, T6 5, T7 6, T8 7);
151impl_tuple_surrogate!(T1 0, T2 1, T3 2, T4 3, T5 4, T6 5, T7 6, T8 7, T9 8);
152impl_tuple_surrogate!(T1 0, T2 1, T3 2, T4 3, T5 4, T6 5, T7 6, T8 7, T9 8, T10 9);
153impl_tuple_surrogate!(T1 0, T2 1, T3 2, T4 3, T5 4, T6 5, T7 6, T8 7, T9 8, T10 9, T11 10);
154impl_tuple_surrogate!(
155    T1 0, T2 1, T3 2, T4 3, T5 4, T6 5, T7 6, T8 7, T9 8, T10 9, T11 10, T12 11,
156);