1use crate::Mode;
17
18pub trait Eject {
20 type Primitive;
21
22 fn eject(&self) -> (Mode, Self::Primitive) {
26 (self.eject_mode(), self.eject_value())
27 }
28
29 fn eject_mode(&self) -> Mode;
33
34 fn eject_value(&self) -> Self::Primitive;
38
39 fn is_constant(&self) -> bool {
43 self.eject_mode().is_constant()
44 }
45
46 fn is_public(&self) -> bool {
50 self.eject_mode().is_public()
51 }
52
53 fn is_private(&self) -> bool {
57 self.eject_mode().is_private()
58 }
59}
60
61impl Eject for Vec<Mode> {
66 type Primitive = Vec<Mode>;
67
68 #[inline]
70 fn eject_mode(&self) -> Mode {
71 match self.first() {
74 Some(first) => Mode::combine(*first, self.iter().copied().skip(1)),
75 None => panic!("Attempted to eject the mode on an empty circuit"),
77 }
78 }
79
80 #[inline]
82 fn eject_value(&self) -> Self::Primitive {
83 self.clone()
84 }
85}
86
87impl<C: Eject<Primitive = P>, P> Eject for Vec<C> {
88 type Primitive = Vec<P>;
89
90 #[inline]
92 fn eject_mode(&self) -> Mode {
93 self.as_slice().eject_mode()
94 }
95
96 #[inline]
98 fn eject_value(&self) -> Self::Primitive {
99 self.as_slice().eject_value()
100 }
101}
102
103impl<C: Eject<Primitive = P>, P, const N: usize> Eject for [C; N] {
104 type Primitive = Vec<P>;
105
106 #[inline]
108 fn eject_mode(&self) -> Mode {
109 self.as_slice().eject_mode()
110 }
111
112 #[inline]
114 fn eject_value(&self) -> Self::Primitive {
115 self.as_slice().eject_value()
116 }
117}
118
119impl<C: Eject<Primitive = P>, P> Eject for &[C] {
120 type Primitive = Vec<P>;
121
122 #[inline]
124 fn eject_mode(&self) -> Mode {
125 match self.first() {
128 Some(first) => Mode::combine(first.eject_mode(), self.iter().skip(1).map(Eject::eject_mode)),
129 None => Mode::Constant,
130 }
132 }
133
134 #[inline]
136 fn eject_value(&self) -> Self::Primitive {
137 self.iter().map(Eject::eject_value).collect()
138 }
139}
140
141macro_rules! eject_tuple {
147 (($t0:ident, 0), $(($ty:ident, $idx:tt)),*) => {
148 impl<'a, $t0: Eject, $($ty: Eject),*> Eject for (&'a $t0, $(&'a $ty),*) {
149 type Primitive = ($t0::Primitive, $( $ty::Primitive ),*);
150
151 #[inline]
153 fn eject_mode(&self) -> Mode {
154 Mode::combine(self.0.eject_mode(), [ $(self.$idx.eject_mode()),* ])
155 }
156
157 #[inline]
159 fn eject_value(&self) -> Self::Primitive {
160 (self.0.eject_value(), $(self.$idx.eject_value()),*)
161 }
162 }
163
164 impl<'a, $t0: Eject, $($ty: Eject),*> Eject for &'a ($t0, $($ty),*) {
165 type Primitive = ($t0::Primitive, $( $ty::Primitive ),*);
166
167 #[inline]
169 fn eject_mode(&self) -> Mode {
170 Mode::combine(self.0.eject_mode(), [ $(self.$idx.eject_mode()),* ])
171 }
172
173 #[inline]
175 fn eject_value(&self) -> Self::Primitive {
176 (self.0.eject_value(), $(self.$idx.eject_value()),*)
177 }
178 }
179 }
180}
181
182eject_tuple!((C0, 0),);
183eject_tuple!((C0, 0), (C1, 1));
184eject_tuple!((C0, 0), (C1, 1), (C2, 2));
185eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3));
186eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4));
187eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5));
188eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6));
189eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7));
190eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8));
191eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8), (C9, 9));
192eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8), (C9, 9), (C10, 10));
193#[rustfmt::skip] eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8), (C9, 9), (C10, 10), (C11, 11));
194#[rustfmt::skip] eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8), (C9, 9), (C10, 10), (C11, 11), (C12, 12));