Skip to content

Instantly share code, notes, and snippets.

@joseluisq
Created June 27, 2021 21:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joseluisq/6812daf269a82668aaa4aa56b9d082fa to your computer and use it in GitHub Desktop.
Save joseluisq/6812daf269a82668aaa4aa56b9d082fa to your computer and use it in GitHub Desktop.
A simple Nginx `try_files` directive parsing example written in Rust
enum Token {
Start,
Middle,
End,
}
/// Parses the Nginx-like `try_files` directive string and returns a vector of tokens.
pub fn parse(val: &str) -> Vec<String> {
let mut kind = Token::Start;
let mut token = String::new();
let mut uris: Vec<String> = vec![];
let chars: Vec<char> = val.trim().chars().collect();
let chars_len = chars.len();
for (i, c) in chars.into_iter().enumerate() {
match kind {
Token::Start => {
if c.eq(&'$') {
kind = Token::Middle;
token.push(c.to_owned());
}
}
Token::Middle => {
if matches!(c, 'a'..='z') {
token.push(c.to_owned());
if token == "$uri" {
kind = Token::End;
if i == chars_len - 1 {
uris.push(token.clone());
}
}
continue;
}
// not valid placeholder
break;
}
Token::End => {
// only `$uri` placeholder support
// check for separator continue to next token
if c.eq(&' ') || i == chars_len - 1 {
if !c.eq(&' ') {
token.push(c);
}
uris.push(token.clone());
token = String::new();
kind = Token::Start;
continue;
}
token.push(c);
}
};
}
uris
}
#[cfg(test)]
mod tests {
use super::parse;
#[test]
fn test_empty_placeholder() {
assert_eq!(parse(""), Vec::new() as Vec<String>)
}
#[test]
fn test_invalid_placeholder() {
assert_eq!(parse("$u ri"), Vec::new() as Vec<String>);
assert_eq!(parse("u ri"), Vec::new() as Vec<String>)
}
#[test]
fn test_invalid_placeholders_mixed() {
assert_eq!(
parse("a/b/$uri.js some/$uri.xml#h1 x/y/z abc-$uri.json?a=1"),
vec!["$uri.js", "$uri.xml#h1", "$uri.json?a=1"]
)
}
#[test]
fn test_one_valid_placeholder() {
assert_eq!(parse("$uri"), vec!["$uri"])
}
#[test]
fn test_many_valid_placeholders() {
assert_eq!(
parse("$uri $uri/index.html $uri.html"),
vec!["$uri", "$uri/index.html", "$uri.html"]
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment