/ circuit / environment / src / helpers / mode.rs
mode.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::prelude::*;
 17  use deltavm_utilities::{FromBytes, ToBytes, error};
 18  use std::io::{Read, Result as IoResult, Write};
 19  
 20  #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 21  pub enum Mode {
 22      Constant,
 23      Public,
 24      Private,
 25  }
 26  
 27  impl Mode {
 28      /// Returns `true` if the mode is a constant.
 29      pub const fn is_constant(&self) -> bool {
 30          matches!(self, Self::Constant)
 31      }
 32  
 33      /// Returns `true` if the mode is public.
 34      pub const fn is_public(&self) -> bool {
 35          matches!(self, Self::Public)
 36      }
 37  
 38      /// Returns `true` if the mode is private.
 39      pub const fn is_private(&self) -> bool {
 40          matches!(self, Self::Private)
 41      }
 42  
 43      /// Parses a string into a mode.
 44      #[inline]
 45      pub fn parse(string: &str) -> ParserResult<Self> {
 46          alt((
 47              map(tag("constant"), |_| Self::Constant),
 48              map(tag("public"), |_| Self::Public),
 49              map(tag("private"), |_| Self::Private),
 50          ))(string)
 51      }
 52  
 53      /// A static helper to deduce the mode from a list of modes.
 54      #[inline]
 55      pub fn combine<M: IntoIterator<Item = Mode>>(starting_mode: Mode, modes: M) -> Mode {
 56          // Initialize the current mode.
 57          let mut current_mode = starting_mode;
 58          // Intuition: Start from `Mode::Constant`, and see if one needs to lift to `Mode::Public` or `Mode::Private`.
 59          //   - If `current_mode == Mode::Constant`, then `current_mode = next_mode`.
 60          //   - If `current_mode == Mode::Public` && `next_mode == Mode::Private`, then `current_mode = next_mode`.
 61          //   - Otherwise, do nothing.
 62          for next_mode in modes {
 63              // If the current mode is `Mode::Private`, we can return early.
 64              if current_mode.is_private() {
 65                  break;
 66              }
 67              // Check if the current mode matches the next mode.
 68              if current_mode != next_mode {
 69                  match (current_mode, next_mode) {
 70                      (Mode::Constant, Mode::Public)
 71                      | (Mode::Constant, Mode::Private)
 72                      | (Mode::Public, Mode::Private) => current_mode = next_mode,
 73                      (_, _) => (), // Do nothing.
 74                  }
 75              }
 76          }
 77          current_mode
 78      }
 79  }
 80  
 81  impl IntoIterator for Mode {
 82      type IntoIter = std::iter::Once<Self>;
 83      type Item = Mode;
 84  
 85      /// Returns an iterator over the mode.
 86      fn into_iter(self) -> Self::IntoIter {
 87          std::iter::once(self)
 88      }
 89  }
 90  
 91  impl FromStr for Mode {
 92      type Err = Error;
 93  
 94      /// Parses a string into a mode.
 95      #[inline]
 96      fn from_str(string: &str) -> Result<Self> {
 97          match Self::parse(string) {
 98              Ok((remainder, object)) => {
 99                  // Ensure the remainder is empty.
100                  ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
101                  // Return the object.
102                  Ok(object)
103              }
104              Err(error) => bail!("Failed to parse string. {error}"),
105          }
106      }
107  }
108  
109  impl Display for Mode {
110      /// Formats the mode as a lowercase string.
111      fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112          match self {
113              Self::Constant => write!(f, "constant"),
114              Self::Public => write!(f, "public"),
115              Self::Private => write!(f, "private"),
116          }
117      }
118  }
119  
120  impl ToBytes for Mode {
121      /// Writes the mode to the writer.
122      fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
123          (*self as u8).write_le(&mut writer)
124      }
125  }
126  
127  impl FromBytes for Mode {
128      /// Reads the mode from the reader.
129      fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
130          let mode = u8::read_le(&mut reader)?;
131          match mode {
132              0 => Ok(Self::Constant),
133              1 => Ok(Self::Public),
134              2 => Ok(Self::Private),
135              _ => Err(error("Invalid mode")),
136          }
137      }
138  }