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 }