snarkvm_synthesizer_program/logic/command/
set.rs1use crate::{
17 FinalizeOperation,
18 Opcode,
19 Operand,
20 traits::{FinalizeStoreTrait, RegistersLoad, StackMatches, StackProgram},
21};
22use console::{
23 network::prelude::*,
24 program::{Identifier, Value},
25};
26
27#[derive(Clone, PartialEq, Eq, Hash)]
30pub struct Set<N: Network> {
31 mapping: Identifier<N>,
33 key: Operand<N>,
35 value: Operand<N>,
37}
38
39impl<N: Network> Set<N> {
40 #[inline]
42 pub const fn opcode() -> Opcode {
43 Opcode::Command("set")
44 }
45
46 #[inline]
48 pub fn operands(&self) -> Vec<Operand<N>> {
49 vec![self.value.clone(), self.key.clone()]
50 }
51
52 #[inline]
54 pub const fn mapping_name(&self) -> &Identifier<N> {
55 &self.mapping
56 }
57
58 #[inline]
60 pub const fn key(&self) -> &Operand<N> {
61 &self.key
62 }
63
64 #[inline]
66 pub const fn value(&self) -> &Operand<N> {
67 &self.value
68 }
69}
70
71impl<N: Network> Set<N> {
72 #[inline]
74 pub fn finalize(
75 &self,
76 stack: &(impl StackMatches<N> + StackProgram<N>),
77 store: &impl FinalizeStoreTrait<N>,
78 registers: &mut impl RegistersLoad<N>,
79 ) -> Result<FinalizeOperation<N>> {
80 if !store.contains_mapping_confirmed(stack.program_id(), &self.mapping)? {
82 bail!("Mapping '{}/{}' does not exist in storage", stack.program_id(), self.mapping);
83 }
84
85 let key = registers.load_plaintext(stack, &self.key)?;
87 let value = Value::Plaintext(registers.load_plaintext(stack, &self.value)?);
89
90 store.update_key_value(*stack.program_id(), self.mapping, key, value)
92 }
93}
94
95impl<N: Network> Parser for Set<N> {
96 #[inline]
98 fn parse(string: &str) -> ParserResult<Self> {
99 let (string, _) = Sanitizer::parse(string)?;
101 let (string, _) = tag(*Self::opcode())(string)?;
103 let (string, _) = Sanitizer::parse_whitespaces(string)?;
105
106 let (string, value) = Operand::parse(string)?;
108 let (string, _) = Sanitizer::parse_whitespaces(string)?;
110
111 let (string, _) = tag("into")(string)?;
113 let (string, _) = Sanitizer::parse_whitespaces(string)?;
115
116 let (string, mapping) = Identifier::parse(string)?;
118 let (string, _) = tag("[")(string)?;
120 let (string, _) = Sanitizer::parse_whitespaces(string)?;
122 let (string, key) = Operand::parse(string)?;
124 let (string, _) = Sanitizer::parse_whitespaces(string)?;
126 let (string, _) = tag("]")(string)?;
128 let (string, _) = Sanitizer::parse_whitespaces(string)?;
130 let (string, _) = tag(";")(string)?;
132
133 Ok((string, Self { mapping, key, value }))
134 }
135}
136
137impl<N: Network> FromStr for Set<N> {
138 type Err = Error;
139
140 #[inline]
142 fn from_str(string: &str) -> Result<Self> {
143 match Self::parse(string) {
144 Ok((remainder, object)) => {
145 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
147 Ok(object)
149 }
150 Err(error) => bail!("Failed to parse string. {error}"),
151 }
152 }
153}
154
155impl<N: Network> Debug for Set<N> {
156 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
158 Display::fmt(self, f)
159 }
160}
161
162impl<N: Network> Display for Set<N> {
163 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
165 write!(f, "{} ", Self::opcode())?;
167 write!(f, "{} into ", self.value)?;
169 write!(f, "{}[{}];", self.mapping, self.key)
171 }
172}
173
174impl<N: Network> FromBytes for Set<N> {
175 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
177 let mapping = Identifier::read_le(&mut reader)?;
179 let key = Operand::read_le(&mut reader)?;
181 let value = Operand::read_le(&mut reader)?;
183 Ok(Self { mapping, key, value })
185 }
186}
187
188impl<N: Network> ToBytes for Set<N> {
189 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
191 self.mapping.write_le(&mut writer)?;
193 self.key.write_le(&mut writer)?;
195 self.value.write_le(&mut writer)
197 }
198}
199
200#[cfg(test)]
201mod tests {
202 use super::*;
203 use console::{network::MainnetV0, program::Register};
204
205 type CurrentNetwork = MainnetV0;
206
207 #[test]
208 fn test_parse() {
209 let (string, set) = Set::<CurrentNetwork>::parse("set r0 into account[r1];").unwrap();
210 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'");
211 assert_eq!(set.mapping, Identifier::from_str("account").unwrap());
212 assert_eq!(set.operands().len(), 2, "The number of operands is incorrect");
213 assert_eq!(set.value, Operand::Register(Register::Locator(0)), "The first operand is incorrect");
214 assert_eq!(set.key, Operand::Register(Register::Locator(1)), "The second operand is incorrect");
215 }
216}