use super::*;
impl<N: Network> Parser for Future<N> {
#[inline]
fn parse(string: &str) -> ParserResult<Self> {
fn parse_arguments<N: Network>(string: &str) -> ParserResult<Vec<Argument<N>>> {
let (string, _) = Sanitizer::parse(string)?;
let (string, _) = tag("[")(string)?;
let (string, _) = Sanitizer::parse(string)?;
let (string, arguments) = separated_list0(
pair(pair(Sanitizer::parse_whitespaces, tag(",")), Sanitizer::parse),
alt((map(Future::parse, Argument::Future), map(Plaintext::parse, Argument::Plaintext))),
)(string)?;
let (string, _) = Sanitizer::parse(string)?;
let (string, _) = tag("]")(string)?;
Ok((string, arguments))
}
let (string, _) = Sanitizer::parse(string)?;
let (string, _) = tag("{")(string)?;
let (string, _) = Sanitizer::parse(string)?;
let (string, _) = tag("program_id")(string)?;
let (string, _) = Sanitizer::parse_whitespaces(string)?;
let (string, _) = tag(":")(string)?;
let (string, _) = Sanitizer::parse_whitespaces(string)?;
let (string, program_id) = ProgramID::parse(string)?;
let (string, _) = Sanitizer::parse_whitespaces(string)?;
let (string, _) = tag(",")(string)?;
let (string, _) = Sanitizer::parse(string)?;
let (string, _) = tag("function_name")(string)?;
let (string, _) = Sanitizer::parse_whitespaces(string)?;
let (string, _) = tag(":")(string)?;
let (string, _) = Sanitizer::parse_whitespaces(string)?;
let (string, function_name) = Identifier::parse(string)?;
let (string, _) = Sanitizer::parse_whitespaces(string)?;
let (string, _) = tag(",")(string)?;
let (string, _) = Sanitizer::parse(string)?;
let (string, _) = tag("arguments")(string)?;
let (string, _) = Sanitizer::parse_whitespaces(string)?;
let (string, _) = tag(":")(string)?;
let (string, _) = Sanitizer::parse_whitespaces(string)?;
let (string, arguments) = parse_arguments(string)?;
let (string, _) = Sanitizer::parse(string)?;
let (string, _) = tag("}")(string)?;
Ok((string, Self::new(program_id, function_name, arguments)))
}
}
impl<N: Network> FromStr for Future<N> {
type Err = Error;
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<N: Network> Debug for Future<N> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Display::fmt(self, f)
}
}
impl<N: Network> Display for Future<N> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.fmt_internal(f, 0)
}
}
impl<N: Network> Future<N> {
fn fmt_internal(&self, f: &mut Formatter, depth: usize) -> fmt::Result {
const INDENT: usize = 2;
write!(f, "{{")?;
write!(
f,
"\n{:indent$}program_id: {program_id},",
"",
indent = (depth + 1) * INDENT,
program_id = self.program_id()
)?;
write!(
f,
"\n{:indent$}function_name: {function_name},",
"",
indent = (depth + 1) * INDENT,
function_name = self.function_name()
)?;
if self.arguments.is_empty() {
write!(f, "\n{:indent$}arguments: []", "", indent = (depth + 1) * INDENT)?;
} else {
write!(f, "\n{:indent$}arguments: [", "", indent = (depth + 1) * INDENT)?;
self.arguments.iter().enumerate().try_for_each(|(i, argument)| {
match argument {
Argument::Plaintext(plaintext) => match i == self.arguments.len() - 1 {
true => {
write!(
f,
"\n{:indent$}{plaintext}",
"",
indent = (depth + 2) * INDENT,
plaintext = plaintext
)
}
false => {
write!(
f,
"\n{:indent$}{plaintext},",
"",
indent = (depth + 2) * INDENT,
plaintext = plaintext
)
}
},
Argument::Future(future) => {
write!(f, "\n{:indent$}", "", indent = (depth + 2) * INDENT)?;
future.fmt_internal(f, depth + 2)?;
match i == self.arguments.len() - 1 {
true => write!(f, "\n{:indent$}", "", indent = (depth + 1) * INDENT),
false => write!(f, ","),
}
}
}
})?;
write!(f, "\n{:indent$}]", "", indent = (depth + 1) * INDENT)?;
}
write!(f, "\n{:indent$}}}", "", indent = depth * INDENT)
}
}
#[cfg(test)]
mod tests {
use super::*;
use snarkvm_console_network::MainnetV0;
type CurrentNetwork = MainnetV0;
#[test]
fn test_parse_future() -> Result<()> {
let expected = r"{
program_id: credits.aleo,
function_name: transfer,
arguments: []
}";
let (remainder, candidate) =
Future::<CurrentNetwork>::parse("{ program_id: credits.aleo, function_name: transfer, arguments: [] }")?;
assert!(remainder.is_empty());
assert_eq!(expected, candidate.to_string());
assert_eq!("", remainder);
let expected = r"{
program_id: credits.aleo,
function_name: transfer_public_to_private,
arguments: [
aleo1g8qul5a44vk22u9uuvaewdcjw4v6xg8wx0llru39nnjn7eu08yrscxe4e2,
100000000u64
]
}";
let (remainder, candidate) = Future::<CurrentNetwork>::parse(
"{ program_id: credits.aleo, function_name: transfer_public_to_private, arguments: [ aleo1g8qul5a44vk22u9uuvaewdcjw4v6xg8wx0llru39nnjn7eu08yrscxe4e2, 100000000u64 ] }",
)?;
assert!(remainder.is_empty());
assert_eq!(expected, candidate.to_string());
assert_eq!("", remainder);
Ok(())
}
}