just 0.4.3

🤖 Just a command runner
Documentation
use crate::common::*;

#[derive(PartialEq, Debug)]
pub struct StringLiteral<'a> {
  pub raw: &'a str,
  pub cooked: Cow<'a, str>,
}

impl<'a> StringLiteral<'a> {
  pub fn new(token: &Token<'a>) -> CompilationResult<'a, StringLiteral<'a>> {
    let raw = &token.lexeme()[1..token.lexeme().len() - 1];

    if let TokenKind::StringRaw = token.kind {
      Ok(StringLiteral {
        cooked: Cow::Borrowed(raw),
        raw,
      })
    } else if let TokenKind::StringCooked = token.kind {
      let mut cooked = String::new();
      let mut escape = false;
      for c in raw.chars() {
        if escape {
          match c {
            'n' => cooked.push('\n'),
            'r' => cooked.push('\r'),
            't' => cooked.push('\t'),
            '\\' => cooked.push('\\'),
            '"' => cooked.push('"'),
            other => {
              return Err(
                token.error(CompilationErrorKind::InvalidEscapeSequence { character: other }),
              );
            }
          }
          escape = false;
          continue;
        }
        if c == '\\' {
          escape = true;
          continue;
        }
        cooked.push(c);
      }
      Ok(StringLiteral {
        raw,
        cooked: Cow::Owned(cooked),
      })
    } else {
      Err(token.error(CompilationErrorKind::Internal {
        message: "cook_string() called on non-string token".to_string(),
      }))
    }
  }
}

impl<'a> Display for StringLiteral<'a> {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    match self.cooked {
      Cow::Borrowed(raw) => write!(f, "'{}'", raw),
      Cow::Owned(_) => write!(f, "\"{}\"", self.raw),
    }
  }
}