/ circuit / environment / src / traits / eject.rs
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));