eject.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the deltavm library. 3 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at: 7 8 // http://www.apache.org/licenses/LICENSE-2.0 9 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 use crate::Mode; 17 18 /// Operations to eject from a circuit environment into primitive form. 19 pub trait Eject { 20 type Primitive; 21 22 /// 23 /// Ejects the mode and primitive value of the circuit type. 24 /// 25 fn eject(&self) -> (Mode, Self::Primitive) { 26 (self.eject_mode(), self.eject_value()) 27 } 28 29 /// 30 /// Ejects the mode of the circuit type. 31 /// 32 fn eject_mode(&self) -> Mode; 33 34 /// 35 /// Ejects the circuit type as a primitive value. 36 /// 37 fn eject_value(&self) -> Self::Primitive; 38 39 /// 40 /// Returns `true` if the circuit is a constant. 41 /// 42 fn is_constant(&self) -> bool { 43 self.eject_mode().is_constant() 44 } 45 46 /// 47 /// Returns `true` if the circuit is a public. 48 /// 49 fn is_public(&self) -> bool { 50 self.eject_mode().is_public() 51 } 52 53 /// 54 /// Returns `true` if the circuit is a private. 55 /// 56 fn is_private(&self) -> bool { 57 self.eject_mode().is_private() 58 } 59 } 60 61 /********************/ 62 /****** Arrays ******/ 63 /********************/ 64 65 impl Eject for Vec<Mode> { 66 type Primitive = Vec<Mode>; 67 68 /// A helper method to deduce the mode from a list of `Eject` circuits. 69 #[inline] 70 fn eject_mode(&self) -> Mode { 71 // TODO (howardwu): Determine if a default mode of `constant` is appropriate. 72 // Retrieve the mode of the first circuit. 73 match self.first() { 74 Some(first) => Mode::combine(*first, self.iter().copied().skip(1)), 75 // None => Mode::Constant, 76 None => panic!("Attempted to eject the mode on an empty circuit"), 77 } 78 } 79 80 /// Ejects the value from each circuit. 81 #[inline] 82 fn eject_value(&self) -> Self::Primitive { 83 self.clone() 84 } 85 } 86 87 impl<C: Eject<Primitive = P>, P> Eject for Vec<C> { 88 type Primitive = Vec<P>; 89 90 /// A helper method to deduce the mode from a list of `Eject` circuits. 91 #[inline] 92 fn eject_mode(&self) -> Mode { 93 self.as_slice().eject_mode() 94 } 95 96 /// Ejects the value from each circuit. 97 #[inline] 98 fn eject_value(&self) -> Self::Primitive { 99 self.as_slice().eject_value() 100 } 101 } 102 103 impl<C: Eject<Primitive = P>, P, const N: usize> Eject for [C; N] { 104 type Primitive = Vec<P>; 105 106 /// A helper method to deduce the mode from a list of `Eject` circuits. 107 #[inline] 108 fn eject_mode(&self) -> Mode { 109 self.as_slice().eject_mode() 110 } 111 112 /// Ejects the value from each circuit. 113 #[inline] 114 fn eject_value(&self) -> Self::Primitive { 115 self.as_slice().eject_value() 116 } 117 } 118 119 impl<C: Eject<Primitive = P>, P> Eject for &[C] { 120 type Primitive = Vec<P>; 121 122 /// A helper method to deduce the mode from a list of `Eject` circuits. 123 #[inline] 124 fn eject_mode(&self) -> Mode { 125 // TODO (howardwu): Determine if a default mode of `constant` is appropriate. 126 // Retrieve the mode of the first circuit. 127 match self.first() { 128 Some(first) => Mode::combine(first.eject_mode(), self.iter().skip(1).map(Eject::eject_mode)), 129 None => Mode::Constant, 130 // None => panic!("Attempted to eject the mode on an empty circuit"), 131 } 132 } 133 134 /// Ejects the value from each circuit. 135 #[inline] 136 fn eject_value(&self) -> Self::Primitive { 137 self.iter().map(Eject::eject_value).collect() 138 } 139 } 140 141 /********************/ 142 /****** Tuples ******/ 143 /********************/ 144 145 /// A helper macro to implement `Eject` for a tuple of `Eject` circuits. 146 macro_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 /// A helper method to deduce the mode from a tuple of `Eject` circuits. 152 #[inline] 153 fn eject_mode(&self) -> Mode { 154 Mode::combine(self.0.eject_mode(), [ $(self.$idx.eject_mode()),* ]) 155 } 156 157 /// Ejects the value from each circuit. 158 #[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 /// A helper method to deduce the mode from a tuple of `Eject` circuits. 168 #[inline] 169 fn eject_mode(&self) -> Mode { 170 Mode::combine(self.0.eject_mode(), [ $(self.$idx.eject_mode()),* ]) 171 } 172 173 /// Ejects the value from each circuit. 174 #[inline] 175 fn eject_value(&self) -> Self::Primitive { 176 (self.0.eject_value(), $(self.$idx.eject_value()),*) 177 } 178 } 179 } 180 } 181 182 eject_tuple!((C0, 0),); 183 eject_tuple!((C0, 0), (C1, 1)); 184 eject_tuple!((C0, 0), (C1, 1), (C2, 2)); 185 eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3)); 186 eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4)); 187 eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5)); 188 eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6)); 189 eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7)); 190 eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8)); 191 eject_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8), (C9, 9)); 192 eject_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));