impl<'a> super::EntityScanner<'a> {
#[inline]
pub fn has_non_null_attribute(&self, start: usize, end: usize, attr_index: usize) -> bool {
let content = &self.bytes[start..end];
let paren_pos = match memchr::memchr(b'(', content) {
Some(p) => p + 1,
None => return false,
};
let mut pos = paren_pos;
let mut current_attr = 0;
let mut depth = 0; let mut in_string = false;
let check_target = |pos: usize, current_attr: usize, depth: usize| -> Option<bool> {
if current_attr == attr_index && depth == 0 {
return Some(match crate::parser::lexical::skip_step_trivia(content, pos) {
Some(p) if p < content.len() => content[p] != b'$',
_ => false,
});
}
None
};
if let Some(result) = check_target(pos, current_attr, depth) {
return result;
}
while pos < content.len() {
let b = content[pos];
if in_string {
if b == b'\'' {
if pos + 1 < content.len() && content[pos + 1] == b'\'' {
pos += 2;
continue;
}
in_string = false;
}
pos += 1;
continue;
}
match b {
b'\'' => {
in_string = true;
pos += 1;
}
b'/' if content.get(pos + 1) == Some(&b'*') => {
match crate::parser::lexical::skip_step_comment(content, pos) {
Some(next) => pos = next,
None => return false,
}
}
b'(' => {
depth += 1;
pos += 1;
}
b')' => {
if depth == 0 {
return false;
}
depth -= 1;
pos += 1;
}
b',' if depth == 0 => {
current_attr += 1;
pos += 1;
match crate::parser::lexical::skip_step_trivia(content, pos) {
Some(p) => pos = p,
None => return false,
}
if let Some(result) = check_target(pos, current_attr, depth) {
return result;
}
}
_ => {
pos += 1;
}
}
}
false
}
}