use std::cell::RefCell;
thread_local! {
static SPANS: RefCell<Vec<Vec<(usize, usize)>>> = const { RefCell::new(Vec::new()) };
static TEXT: RefCell<Vec<String>> = const { RefCell::new(Vec::new()) };
}
pub(crate) fn with_spans<R>(f: impl FnOnce(&mut Vec<(usize, usize)>) -> R) -> R {
let mut buf = SPANS
.with(|stack| stack.borrow_mut().pop())
.unwrap_or_default();
buf.clear();
let result = f(&mut buf);
SPANS.with(|stack| {
if let Ok(mut stack) = stack.try_borrow_mut() {
stack.push(buf);
}
});
result
}
pub(crate) fn with_text<R>(f: impl FnOnce(&mut String) -> R) -> R {
let mut buf = TEXT
.with(|stack| stack.borrow_mut().pop())
.unwrap_or_default();
buf.clear();
let result = f(&mut buf);
TEXT.with(|stack| {
if let Ok(mut stack) = stack.try_borrow_mut() {
stack.push(buf);
}
});
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_buffer_arrives_empty_however_it_was_left() {
with_spans(|spans| spans.extend([(0, 1), (1, 2)]));
with_spans(|spans| assert!(spans.is_empty(), "spans leaked between calls"));
}
#[test]
fn a_nested_call_gets_its_own_buffer() {
with_spans(|outer| {
outer.extend([(0, 3), (3, 6)]);
with_spans(|inner| {
assert!(inner.is_empty());
inner.push((9, 9));
});
assert_eq!(
outer,
&[(0, 3), (3, 6)],
"a nested call overwrote the outer buffer"
);
});
}
#[test]
fn a_nested_call_reuses_a_buffer_across_calls() {
with_spans(|_outer| {
with_spans(|inner| inner.extend((0..64).map(|i| (i, i + 1))));
});
with_spans(|_outer| {
with_spans(|inner| {
assert!(inner.is_empty(), "nested buffer arrived dirty");
assert!(
inner.capacity() >= 64,
"nested call allocated instead of reusing"
);
});
});
}
#[test]
fn capacity_survives_between_calls() {
with_spans(|spans| spans.extend((0..64).map(|i| (i, i + 1))));
with_spans(|spans| {
assert!(
spans.capacity() >= 64,
"buffer was reallocated instead of reused"
)
});
}
}