set.rs
1 // Copyright (c) 2025 ADnet Contributors 2 // This file is part of the AlphaVM 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::{FinalizeOperation, FinalizeStoreTrait, Opcode, Operand, RegistersTrait, StackTrait}; 17 use console::{ 18 network::prelude::*, 19 program::{Identifier, Value}, 20 }; 21 22 /// A set command, e.g. `set r1 into mapping[r0];` 23 /// Sets the `key` entry as `value` in `mapping`. 24 #[derive(Clone, PartialEq, Eq, Hash)] 25 pub struct Set<N: Network> { 26 /// The mapping name. 27 mapping: Identifier<N>, 28 /// The operands. 29 operands: [Operand<N>; 2], 30 } 31 32 impl<N: Network> Set<N> { 33 /// Returns the opcode. 34 #[inline] 35 pub const fn opcode() -> Opcode { 36 Opcode::Command("set") 37 } 38 39 /// Returns the operands in the operation. 40 #[inline] 41 pub fn operands(&self) -> &[Operand<N>] { 42 &self.operands 43 } 44 45 /// Returns the mapping name. 46 #[inline] 47 pub const fn mapping_name(&self) -> &Identifier<N> { 48 &self.mapping 49 } 50 51 /// Returns the operand containing the key. 52 #[inline] 53 pub const fn key(&self) -> &Operand<N> { 54 &self.operands[0] 55 } 56 57 /// Returns the operand containing the value. 58 #[inline] 59 pub const fn value(&self) -> &Operand<N> { 60 &self.operands[1] 61 } 62 } 63 64 impl<N: Network> Set<N> { 65 /// Finalizes the command. 66 pub fn finalize( 67 &self, 68 stack: &impl StackTrait<N>, 69 store: &impl FinalizeStoreTrait<N>, 70 registers: &mut impl RegistersTrait<N>, 71 ) -> Result<FinalizeOperation<N>> { 72 // Ensure the mapping exists. 73 if !store.contains_mapping_speculative(stack.program_id(), &self.mapping)? { 74 bail!("Mapping '{}/{}' does not exist", stack.program_id(), self.mapping); 75 } 76 77 // Load the key operand as a plaintext. 78 let key = registers.load_plaintext(stack, self.key())?; 79 // Load the value operand as a plaintext. 80 let value = Value::Plaintext(registers.load_plaintext(stack, self.value())?); 81 82 // Update the value in storage, and return the finalize operation. 83 store.update_key_value(*stack.program_id(), self.mapping, key, value) 84 } 85 } 86 87 impl<N: Network> Parser for Set<N> { 88 /// Parses a string into an operation. 89 fn parse(string: &str) -> ParserResult<Self> { 90 // Parse the whitespace and comments from the string. 91 let (string, _) = Sanitizer::parse(string)?; 92 // Parse the opcode from the string. 93 let (string, _) = tag(*Self::opcode())(string)?; 94 // Parse the whitespace from the string. 95 let (string, _) = Sanitizer::parse_whitespaces(string)?; 96 97 // Parse the value operand from the string. 98 let (string, value) = Operand::parse(string)?; 99 // Parse the whitespace from the string. 100 let (string, _) = Sanitizer::parse_whitespaces(string)?; 101 102 // Parse the "into" keyword from the string. 103 let (string, _) = tag("into")(string)?; 104 // Parse the whitespace from the string. 105 let (string, _) = Sanitizer::parse_whitespaces(string)?; 106 107 // Parse the mapping name from the string. 108 let (string, mapping) = Identifier::parse(string)?; 109 // Parse the "[" from the string. 110 let (string, _) = tag("[")(string)?; 111 // Parse the whitespace from the string. 112 let (string, _) = Sanitizer::parse_whitespaces(string)?; 113 // Parse the key operand from the string. 114 let (string, key) = Operand::parse(string)?; 115 // Parse the whitespace from the string. 116 let (string, _) = Sanitizer::parse_whitespaces(string)?; 117 // Parse the "]" from the string. 118 let (string, _) = tag("]")(string)?; 119 // Parse the whitespace from the string. 120 let (string, _) = Sanitizer::parse_whitespaces(string)?; 121 // Parse the ";" from the string. 122 let (string, _) = tag(";")(string)?; 123 124 Ok((string, Self { mapping, operands: [key, value] })) 125 } 126 } 127 128 impl<N: Network> FromStr for Set<N> { 129 type Err = Error; 130 131 /// Parses a string into the command. 132 #[inline] 133 fn from_str(string: &str) -> Result<Self> { 134 match Self::parse(string) { 135 Ok((remainder, object)) => { 136 // Ensure the remainder is empty. 137 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\""); 138 // Return the object. 139 Ok(object) 140 } 141 Err(error) => bail!("Failed to parse string. {error}"), 142 } 143 } 144 } 145 146 impl<N: Network> Debug for Set<N> { 147 /// Prints the command as a string. 148 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 149 Display::fmt(self, f) 150 } 151 } 152 153 impl<N: Network> Display for Set<N> { 154 /// Prints the command to a string. 155 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 156 // Print the command. 157 write!(f, "{} ", Self::opcode())?; 158 // Print the value operand. 159 write!(f, "{} into ", self.value())?; 160 // Print the mapping and key operand. 161 write!(f, "{}[{}];", self.mapping, self.key()) 162 } 163 } 164 165 impl<N: Network> FromBytes for Set<N> { 166 /// Reads the command from a buffer. 167 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> { 168 // Read the mapping name. 169 let mapping = Identifier::read_le(&mut reader)?; 170 // Read the key operand. 171 let key = Operand::read_le(&mut reader)?; 172 // Read the value operand. 173 let value = Operand::read_le(&mut reader)?; 174 // Return the command. 175 Ok(Self { mapping, operands: [key, value] }) 176 } 177 } 178 179 impl<N: Network> ToBytes for Set<N> { 180 /// Writes the operation to a buffer. 181 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> { 182 // Write the mapping name. 183 self.mapping.write_le(&mut writer)?; 184 // Write the key operand. 185 self.key().write_le(&mut writer)?; 186 // Write the value operand. 187 self.value().write_le(&mut writer) 188 } 189 } 190 191 #[cfg(test)] 192 mod tests { 193 use super::*; 194 use console::{network::MainnetV0, program::Register}; 195 196 type CurrentNetwork = MainnetV0; 197 198 #[test] 199 fn test_parse() { 200 let (string, set) = Set::<CurrentNetwork>::parse("set r0 into account[r1];").unwrap(); 201 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 202 assert_eq!(set.mapping, Identifier::from_str("account").unwrap()); 203 assert_eq!(set.operands().len(), 2, "The number of operands is incorrect"); 204 assert_eq!(set.value(), &Operand::Register(Register::Locator(0)), "The first operand is incorrect"); 205 assert_eq!(set.key(), &Operand::Register(Register::Locator(1)), "The second operand is incorrect"); 206 } 207 }