use crate::Mode;
pub trait Eject {
type Primitive;
fn eject(&self) -> (Mode, Self::Primitive) {
(self.eject_mode(), self.eject_value())
}
fn eject_mode(&self) -> Mode;
fn eject_value(&self) -> Self::Primitive;
fn is_constant(&self) -> bool {
self.eject_mode().is_constant()
}
fn is_public(&self) -> bool {
self.eject_mode().is_public()
}
fn is_private(&self) -> bool {
self.eject_mode().is_private()
}
}
impl Eject for Vec<Mode> {
type Primitive = Vec<Mode>;
#[inline]
fn eject_mode(&self) -> Mode {
match self.first() {
Some(first) => Mode::combine(*first, self.iter().copied().skip(1)),
None => panic!("Attempted to eject the mode on an empty circuit"),
}
}
#[inline]
fn eject_value(&self) -> Self::Primitive {
self.clone()
}
}
impl<C: Eject<Primitive = P>, P> Eject for Vec<C> {
type Primitive = Vec<P>;
#[inline]
fn eject_mode(&self) -> Mode {
self.as_slice().eject_mode()
}
#[inline]
fn eject_value(&self) -> Self::Primitive {
self.as_slice().eject_value()
}
}
impl<C: Eject<Primitive = P>, P, const N: usize> Eject for [C; N] {
type Primitive = Vec<P>;
#[inline]
fn eject_mode(&self) -> Mode {
self.as_slice().eject_mode()
}
#[inline]
fn eject_value(&self) -> Self::Primitive {
self.as_slice().eject_value()
}
}
impl<C: Eject<Primitive = P>, P> Eject for &[C] {
type Primitive = Vec<P>;
#[inline]
fn eject_mode(&self) -> Mode {
match self.first() {
Some(first) => Mode::combine(first.eject_mode(), self.iter().skip(1).map(Eject::eject_mode)),
None => Mode::Constant,
}
}
#[inline]
fn eject_value(&self) -> Self::Primitive {
self.iter().map(Eject::eject_value).collect()
}
}
macro_rules! eject_tuple {
(($t0:ident, 0), $(($ty:ident, $idx:tt)),*) => {
impl<'a, $t0: Eject, $($ty: Eject),*> Eject for (&'a $t0, $(&'a $ty),*) {
type Primitive = ($t0::Primitive, $( $ty::Primitive ),*);
#[inline]
fn eject_mode(&self) -> Mode {
Mode::combine(self.0.eject_mode(), [ $(self.$idx.eject_mode()),* ])
}
#[inline]
fn eject_value(&self) -> Self::Primitive {
(self.0.eject_value(), $(self.$idx.eject_value()),*)
}
}
impl<'a, $t0: Eject, $($ty: Eject),*> Eject for &'a ($t0, $($ty),*) {
type Primitive = ($t0::Primitive, $( $ty::Primitive ),*);
#[inline]
fn eject_mode(&self) -> Mode {
Mode::combine(self.0.eject_mode(), [ $(self.$idx.eject_mode()),* ])
}
#[inline]
fn eject_value(&self) -> Self::Primitive {
(self.0.eject_value(), $(self.$idx.eject_value()),*)
}
}
}
}
eject_tuple!((C0, 0),);
eject_tuple!((C0, 0), (C1, 1));
eject_tuple!((C0, 0), (C1, 1), (C2, 2));
eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3));
eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4));
eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5));
eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6));
eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7));
eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8));
eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8), (C9, 9));
eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8), (C9, 9), (C10, 10));
#[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));
#[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));