use crate::prelude::*;
use snarkvm_utilities::{FromBytes, ToBytes, error};
use std::io::{Read, Result as IoResult, Write};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Mode {
Constant,
Public,
Private,
}
impl Mode {
pub const fn is_constant(&self) -> bool {
matches!(self, Self::Constant)
}
pub const fn is_public(&self) -> bool {
matches!(self, Self::Public)
}
pub const fn is_private(&self) -> bool {
matches!(self, Self::Private)
}
#[inline]
pub fn parse(string: &str) -> ParserResult<Self> {
alt((
map(tag("constant"), |_| Self::Constant),
map(tag("public"), |_| Self::Public),
map(tag("private"), |_| Self::Private),
))(string)
}
#[inline]
pub fn combine<M: IntoIterator<Item = Mode>>(starting_mode: Mode, modes: M) -> Mode {
let mut current_mode = starting_mode;
for next_mode in modes {
if current_mode.is_private() {
break;
}
if current_mode != next_mode {
match (current_mode, next_mode) {
(Mode::Constant, Mode::Public)
| (Mode::Constant, Mode::Private)
| (Mode::Public, Mode::Private) => current_mode = next_mode,
(_, _) => (), }
}
}
current_mode
}
}
impl IntoIterator for Mode {
type IntoIter = std::iter::Once<Self>;
type Item = Mode;
fn into_iter(self) -> Self::IntoIter {
std::iter::once(self)
}
}
impl FromStr for Mode {
type Err = Error;
#[inline]
fn from_str(string: &str) -> Result<Self> {
match Self::parse(string) {
Ok((remainder, object)) => {
ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
Ok(object)
}
Err(error) => bail!("Failed to parse string. {error}"),
}
}
}
impl Display for Mode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Constant => write!(f, "constant"),
Self::Public => write!(f, "public"),
Self::Private => write!(f, "private"),
}
}
}
impl ToBytes for Mode {
fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
(*self as u8).write_le(&mut writer)
}
}
impl FromBytes for Mode {
fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
let mode = u8::read_le(&mut reader)?;
match mode {
0 => Ok(Self::Constant),
1 => Ok(Self::Public),
2 => Ok(Self::Private),
_ => Err(error("Invalid mode")),
}
}
}