use super::*;
impl<N: Network> Parser for ViewCore<N> {
#[inline]
fn parse(string: &str) -> ParserResult<Self> {
let (string, _) = Sanitizer::parse(string)?;
let (string, _) = tag(Self::type_name())(string)?;
let (string, _) = Sanitizer::parse_whitespaces(string)?;
let (string, name) = Identifier::<N>::parse(string)?;
let (string, _) = Sanitizer::parse_whitespaces(string)?;
let (string, _) = tag(":")(string)?;
let (string, inputs) = many0(Input::parse)(string)?;
let (string, commands) = many0(Command::<N>::parse)(string)?;
let (string, outputs) = many0(Output::parse)(string)?;
map_res(take(0usize), move |_| {
let mut view = Self::new(name);
inputs.iter().cloned().try_for_each(|input| view.add_input(input))?;
commands.iter().cloned().try_for_each(|command| view.add_command(command))?;
outputs.iter().cloned().try_for_each(|output| view.add_output(output))?;
Ok::<_, Error>(view)
})(string)
}
}
impl<N: Network> FromStr for ViewCore<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 ViewCore<N> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Display::fmt(self, f)
}
}
impl<N: Network> Display for ViewCore<N> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{} {}:", Self::type_name(), self.name)?;
self.inputs.iter().try_for_each(|input| write!(f, "\n {input}"))?;
self.commands.iter().try_for_each(|command| write!(f, "\n {command}"))?;
self.outputs.iter().try_for_each(|output| write!(f, "\n {output}"))
}
}
#[cfg(test)]
mod tests {
use super::*;
use console::network::MainnetV0;
type CurrentNetwork = MainnetV0;
#[test]
fn test_view_parse() {
let view = ViewCore::<CurrentNetwork>::parse(
r"
view foo:
input r0 as field.public;
input r1 as field.public;
add r0 r1 into r2;
output r2 as field.public;",
)
.unwrap()
.1;
assert_eq!("foo", view.name().to_string());
assert_eq!(2, view.inputs().len());
assert_eq!(1, view.commands().len());
assert_eq!(1, view.outputs().len());
}
#[test]
fn test_view_parse_no_inputs() {
let view = ViewCore::<CurrentNetwork>::parse(
r"
view foo:
add 1u64 2u64 into r0;
output r0 as u64.public;",
)
.unwrap()
.1;
assert_eq!("foo", view.name().to_string());
assert_eq!(0, view.inputs().len());
assert_eq!(1, view.commands().len());
assert_eq!(1, view.outputs().len());
}
#[test]
fn test_view_display() {
let expected = r"view foo:
input r0 as field.public;
input r1 as field.public;
add r0 r1 into r2;
output r2 as field.public;";
let view = ViewCore::<CurrentNetwork>::parse(expected).unwrap().1;
assert_eq!(expected, format!("{view}"));
}
#[test]
fn test_view_parse_fails() {
assert!(
ViewCore::<CurrentNetwork>::from_str(
r"
foo:
add 1u64 2u64 into r0;
output r0 as u64.public;"
)
.is_err()
);
assert!(
ViewCore::<CurrentNetwork>::from_str(
r"
view foo
add 1u64 2u64 into r0;
output r0 as u64.public;"
)
.is_err()
);
assert!(
ViewCore::<CurrentNetwork>::from_str(
r"
view foo:
input r0 as u64.public;
set r0 into balances[r0];
output r0 as u64.public;"
)
.is_err()
);
}
#[test]
fn test_view_parse_no_outputs_guard() {
let view = ViewCore::<CurrentNetwork>::parse(
r"
view require_zero:
input r0 as u64.public;
assert.eq r0 0u64;",
)
.unwrap()
.1;
assert_eq!("require_zero", view.name().to_string());
assert_eq!(1, view.inputs().len());
assert_eq!(1, view.commands().len());
assert_eq!(0, view.outputs().len());
}
#[test]
fn test_view_parse_no_commands_passthrough() {
let view = ViewCore::<CurrentNetwork>::parse(
r"
view identity:
input r0 as u64.public;
output r0 as u64.public;",
)
.unwrap()
.1;
assert_eq!("identity", view.name().to_string());
assert_eq!(1, view.inputs().len());
assert_eq!(0, view.commands().len());
assert_eq!(1, view.outputs().len());
}
#[test]
fn test_view_parse_fully_empty() {
let view = ViewCore::<CurrentNetwork>::parse(
r"
view noop:",
)
.unwrap()
.1;
assert_eq!("noop", view.name().to_string());
assert_eq!(0, view.inputs().len());
assert_eq!(0, view.commands().len());
assert_eq!(0, view.outputs().len());
}
}