await_.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::{Opcode, Operand}; 17 use console::{network::prelude::*, program::Register}; 18 19 /// An await command, e.g. `await r0;`. 20 /// Awaits the result of an asynchronous call (a future). 21 /// Note that asynchronous calls currently do not return a value. 22 #[derive(Clone, PartialEq, Eq, Hash)] 23 pub struct Await<N: Network> { 24 /// The operands. 25 /// Note: Byte and string parsing guarantees that this is a single register operand. 26 operands: [Operand<N>; 1], 27 } 28 29 impl<N: Network> Await<N> { 30 /// Returns the opcode. 31 #[inline] 32 pub const fn opcode() -> Opcode { 33 Opcode::Command("await") 34 } 35 36 /// Returns the operands in the command. 37 #[inline] 38 pub fn operands(&self) -> &[Operand<N>] { 39 &self.operands 40 } 41 42 /// Returns the register containing the future. 43 #[inline] 44 pub fn register(&self) -> &Register<N> { 45 // Note: This byte and string parsing guarantees that the operand is a single register. 46 let Operand::Register(register) = &self.operands[0] else { 47 unreachable!("The operands of an await command must be a single register.") 48 }; 49 // Return the register. 50 register 51 } 52 } 53 54 impl<N: Network> Parser for Await<N> { 55 /// Parses a string into an operation. 56 #[inline] 57 fn parse(string: &str) -> ParserResult<Self> { 58 // Parse the whitespace and comments from the string. 59 let (string, _) = Sanitizer::parse(string)?; 60 // Parse the opcode from the string. 61 let (string, _) = tag(*Self::opcode())(string)?; 62 // Parse the whitespace from the string. 63 let (string, _) = Sanitizer::parse_whitespaces(string)?; 64 // Parse the register from the string. 65 let (string, register) = Register::parse(string)?; 66 // Parse the whitespace from the string. 67 let (string, _) = Sanitizer::parse_whitespaces(string)?; 68 // Parse the ';' from the string. 69 let (string, _) = tag(";")(string)?; 70 71 Ok((string, Self { operands: [Operand::Register(register)] })) 72 } 73 } 74 75 impl<N: Network> FromStr for Await<N> { 76 type Err = Error; 77 78 /// Parses a string into the command. 79 #[inline] 80 fn from_str(string: &str) -> Result<Self> { 81 match Self::parse(string) { 82 Ok((remainder, object)) => { 83 // Ensure the remainder is empty. 84 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\""); 85 // Return the object. 86 Ok(object) 87 } 88 Err(error) => bail!("Failed to parse string. {error}"), 89 } 90 } 91 } 92 93 impl<N: Network> Debug for Await<N> { 94 /// Prints the command as a string. 95 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 96 Display::fmt(self, f) 97 } 98 } 99 100 impl<N: Network> Display for Await<N> { 101 /// Prints the command to a string. 102 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 103 // Print the command. 104 write!(f, "await {};", self.register()) 105 } 106 } 107 108 impl<N: Network> FromBytes for Await<N> { 109 /// Reads the command from a buffer. 110 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> { 111 // Read the register. 112 let register = Register::read_le(&mut reader)?; 113 114 Ok(Self { operands: [Operand::Register(register)] }) 115 } 116 } 117 118 impl<N: Network> ToBytes for Await<N> { 119 /// Writes the operation to a buffer. 120 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> { 121 // Write the register. 122 self.register().write_le(&mut writer)?; 123 Ok(()) 124 } 125 } 126 127 #[cfg(test)] 128 mod tests { 129 use super::*; 130 use console::{network::MainnetV0, program::Register}; 131 132 type CurrentNetwork = MainnetV0; 133 134 #[test] 135 fn test_parse() { 136 let (string, await_) = Await::<CurrentNetwork>::parse("await r1;").unwrap(); 137 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 138 assert_eq!(await_.register(), &Register::Locator(1)); 139 } 140 }