use super::*;
impl<E: Environment> Parser for IdentifierLiteral<E> {
#[inline]
fn parse(string: &str) -> ParserResult<Self> {
let (string, _) = tag("'")(string)?;
let (string, literal) =
map_res(recognize(pair(alpha1, many0(alt((alphanumeric1, tag("_")))))), Self::new)(string)?;
let (string, _) = tag("'")(string)?;
Ok((string, literal))
}
}
impl<E: Environment> FromStr for IdentifierLiteral<E> {
type Err = Error;
#[inline]
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<E: Environment> Debug for IdentifierLiteral<E> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Display::fmt(self, f)
}
}
impl<E: Environment> Display for IdentifierLiteral<E> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let n = self.length() as usize;
let s = core::str::from_utf8(&self.bytes[..n]).map_err(|_| fmt::Error)?;
write!(f, "'{s}'")
}
}
#[cfg(test)]
mod tests {
use super::*;
use snarkvm_console_network_environment::Console;
type CurrentEnvironment = Console;
#[test]
fn test_parse_valid() {
let (remainder, literal) = IdentifierLiteral::<CurrentEnvironment>::parse("'hello'").unwrap();
assert_eq!(remainder, "");
assert_eq!(literal.to_string(), "'hello'");
let (remainder, literal) = IdentifierLiteral::<CurrentEnvironment>::parse("'hello_world_42'").unwrap();
assert_eq!(remainder, "");
assert_eq!(literal.to_string(), "'hello_world_42'");
let (remainder, literal) = IdentifierLiteral::<CurrentEnvironment>::parse("'a'").unwrap();
assert_eq!(remainder, "");
assert_eq!(literal.to_string(), "'a'");
}
#[test]
fn test_parse_with_remainder() {
let (remainder, literal) = IdentifierLiteral::<CurrentEnvironment>::parse("'hello' rest").unwrap();
assert_eq!(remainder, " rest");
assert_eq!(literal.to_string(), "'hello'");
}
#[test]
fn test_parse_invalid() {
assert!(IdentifierLiteral::<CurrentEnvironment>::parse("hello").is_err());
assert!(IdentifierLiteral::<CurrentEnvironment>::parse("'hello").is_err());
assert!(IdentifierLiteral::<CurrentEnvironment>::parse("''").is_err());
assert!(IdentifierLiteral::<CurrentEnvironment>::parse("'hello world'").is_err());
assert!(IdentifierLiteral::<CurrentEnvironment>::parse("'1abc'").is_err());
}
#[test]
fn test_parse_roundtrip() {
let original = IdentifierLiteral::<CurrentEnvironment>::new("hello_world").unwrap();
let display = original.to_string();
let recovered = IdentifierLiteral::<CurrentEnvironment>::from_str(&display).unwrap();
assert_eq!(original, recovered);
}
#[test]
fn test_display() {
let literal = IdentifierLiteral::<CurrentEnvironment>::new("hello").unwrap();
assert_eq!(literal.to_string(), "'hello'");
}
#[test]
fn test_parse_random() {
const ITERATIONS: u64 = 1000;
let mut rng = TestRng::default();
for _ in 0..ITERATIONS {
let expected = IdentifierLiteral::<CurrentEnvironment>::rand(&mut rng);
let display = expected.to_string();
let recovered = IdentifierLiteral::<CurrentEnvironment>::from_str(&display).unwrap();
assert_eq!(expected, recovered);
}
}
}