Skip to content

Instantly share code, notes, and snippets.

@dvdhrm
Created October 18, 2018 17:25
Show Gist options
  • Save dvdhrm/5a951931e47479f53dd03b1e0fe9a1e6 to your computer and use it in GitHub Desktop.
Save dvdhrm/5a951931e47479f53dd03b1e0fe9a1e6 to your computer and use it in GitHub Desktop.
fn unquote_single<'a>(acc: &mut String, source: &'a str) -> Option<&'a str> {
if let Some(end) = source.find('\'') {
acc.push_str(&source[..end]);
Some(&source[end + 1..])
} else {
None
}
}
fn unquote_double<'a>(acc: &mut String, source: &'a str) -> Option<&'a str> {
None
}
fn unquote_escape<'a>(acc: &mut String, source: &'a str) -> Option<&'a str> {
None
}
fn unquote(mut source: &str) -> Option<String> {
let mut acc = String::with_capacity(source.len() / 2);
//
// Unstable `std::String` allows passing a `&[char]` instead of the closure to find(), and
// it will search for any occurance of any character provided in the slice. This is still
// unstable and hidden behind the 'pattern' RFC.
// Note that it is very likely implemented similarly to the closure we use here, so we
// should be good. Maybe in the future someone will fallback to an optimized `strspn(3)`.
//
while let Some(idx) = source.find(|c| (c == '\'' || c == '"' || c == '\\')) {
//
// Push anything up to the first quote/escape literally. Then depending on the
// following character perform the required unquote operation. Update `source` to
// point to the next character to continue with.
//
let (front, tail) = source.split_at(idx);
let mut i_tail = tail.chars();
let op = i_tail.next();
acc.push_str(front);
source = i_tail.as_str();
source = match op {
Some('\'') => unquote_single(&mut acc, source)?,
Some('"') => unquote_double(&mut acc, source)?,
Some('\\') => unquote_escape(&mut acc, source)?,
_ => panic!(),
};
}
acc.push_str(source);
Some(acc)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment