Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
strip-json-comments rust (untested, kept here so i can find it later)
pub fn strip_json_comments(s: &str) -> String {
let mut result = String::with_capacity(s.len());
let mut iter = s.chars();
while let Some(c) = iter.next() {
if c == '"' {
// It's a string, skip to end without touching any comments inside.
result.push(c);
while let Some(c) = iter.next() {
result.push(c);
// Skip escape sequence.
if c == '\\' {
result.extend(iter.next());
continue;
}
if c == '"' {
break;
}
}
} else if c == '/' {
// A comment. Skip past it, and replace it's non-whitespace
// characters with spaces. This preserves line/column numbering
// in the case that serde complains about something.
#[inline]
fn as_whitespace(c: char) -> char {
if c.is_whitespace() {
c
} else {
' '
}
}
match iter.next() {
Some('/') => {
result.push(' '); // first '/'
result.push(' '); // second '/'
while let Some(c) = iter.next() {
result.push(as_whitespace(c));
if c == '\n' {
break;
}
}
}
Some('*') => {
// Multiline comment. Don't allow nesting, since it's easier not
// to and e.g. JS doesn't anyway.
result.push(' '); // replace '/'
result.push(' '); // replace '*'
while let Some(c) = iter.next() {
result.push(as_whitespace(c));
if c == '*' {
let c2 = iter.next();
result.extend(c2.map(as_whitespace));
if let Some('/') = c2 {
result.push(' ');
break;
}
}
}
}
Some(c2) => {
// Regular charac
result.extend([c, c2].iter().copied());
}
None => {}
}
} else {
result.push(c);
}
}
result
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment