#![allow(
clippy::module_name_repetitions,
clippy::too_many_lines,
clippy::too_many_arguments,
clippy::map_unwrap_or,
clippy::option_if_let_else,
clippy::elidable_lifetime_names,
clippy::items_after_statements,
clippy::needless_pass_by_value,
clippy::single_match_else,
clippy::manual_let_else,
clippy::match_same_arms,
clippy::missing_const_for_fn,
clippy::single_char_pattern,
clippy::naive_bytecount,
clippy::expect_used,
clippy::redundant_pub_crate,
clippy::used_underscore_binding,
clippy::redundant_field_names,
clippy::struct_field_names,
clippy::redundant_else,
clippy::similar_names
)]
use super::Edge;
pub(crate) struct ChildCursor<'a> {
pub(crate) edges: &'a [&'a Edge],
pub(crate) consumed: Vec<bool>,
}
impl<'a> ChildCursor<'a> {
pub(crate) fn new(edges: &'a [&'a Edge]) -> Self {
Self {
edges,
consumed: vec![false; edges.len()],
}
}
pub(crate) fn take_field(&mut self, field_name: &str) -> Option<&'a Edge> {
for (i, edge) in self.edges.iter().enumerate() {
if !self.consumed[i] && edge.kind.as_ref() == field_name {
self.consumed[i] = true;
return Some(edge);
}
}
None
}
pub(crate) fn has_field(&self, field_name: &str) -> bool {
self.peek_field(field_name).is_some()
}
pub(crate) fn peek_field(&self, field_name: &str) -> Option<&'a Edge> {
self.edges
.iter()
.enumerate()
.find(|(i, edge)| !self.consumed[*i] && edge.kind.as_ref() == field_name)
.map(|(_, edge)| *edge)
}
#[cfg(test)]
pub(crate) fn has_matching(&self, predicate: impl Fn(&Edge) -> bool) -> bool {
self.edges
.iter()
.enumerate()
.any(|(i, edge)| !self.consumed[i] && predicate(edge))
}
pub(crate) fn take_matching(&mut self, predicate: impl Fn(&Edge) -> bool) -> Option<&'a Edge> {
for (i, edge) in self.edges.iter().enumerate() {
if !self.consumed[i] && predicate(edge) {
self.consumed[i] = true;
return Some(edge);
}
}
None
}
}
thread_local! {
pub(crate) static EMIT_DEPTH: std::cell::Cell<usize> = const { std::cell::Cell::new(0) };
pub(crate) static EMIT_MU_FRAMES: std::cell::RefCell<std::collections::HashSet<(String, String, usize)>> =
std::cell::RefCell::new(std::collections::HashSet::new());
pub(crate) static EMIT_FIELD_CONTEXT: std::cell::RefCell<Option<String>> =
const { std::cell::RefCell::new(None) };
}
pub(crate) struct FieldContextGuard(Option<String>);
impl Drop for FieldContextGuard {
fn drop(&mut self) {
EMIT_FIELD_CONTEXT.with(|f| *f.borrow_mut() = self.0.take());
}
}
pub(crate) fn push_field_context(name: &str) -> FieldContextGuard {
let prev = EMIT_FIELD_CONTEXT.with(|f| f.borrow_mut().replace(name.to_owned()));
FieldContextGuard(prev)
}
pub(crate) fn clear_field_context() -> FieldContextGuard {
let prev = EMIT_FIELD_CONTEXT.with(|f| f.borrow_mut().take());
FieldContextGuard(prev)
}
pub(crate) fn current_field_context() -> Option<String> {
EMIT_FIELD_CONTEXT.with(|f| f.borrow().clone())
}