use std::borrow::Cow;
use std::cell::RefCell;
const STRING_POOL_MAX: usize = 128;
const MASKS_POOL_MAX: usize = 16;
#[derive(Clone)]
pub struct TextVariant<'a> {
pub text: Cow<'a, str>,
pub mask: u64,
pub is_ascii: bool,
}
pub type ProcessedTextMasks<'a> = Vec<TextVariant<'a>>;
pub(crate) struct TransformThreadState {
pub(crate) tree_node_indices: Vec<usize>,
pub(crate) masks_pool: Vec<ProcessedTextMasks<'static>>,
}
impl TransformThreadState {
pub(crate) const fn new() -> Self {
Self {
tree_node_indices: Vec::new(),
masks_pool: Vec::new(),
}
}
}
#[thread_local]
pub(crate) static STRING_POOL: RefCell<Vec<String>> = RefCell::new(Vec::new());
#[thread_local]
pub(crate) static TRANSFORM_STATE: RefCell<TransformThreadState> =
RefCell::new(TransformThreadState::new());
pub(crate) fn get_string_from_pool(capacity: usize) -> String {
if let Some(mut s) = STRING_POOL.borrow_mut().pop() {
s.clear();
if s.capacity() < capacity {
s.reserve(capacity - s.capacity());
}
s
} else {
String::with_capacity(capacity)
}
}
pub(crate) fn return_string_to_pool(s: String) {
let mut pool = STRING_POOL.borrow_mut();
if pool.len() < STRING_POOL_MAX {
pool.push(s);
}
}
pub(crate) fn return_processed_string_to_pool(mut text_masks: ProcessedTextMasks) {
for TextVariant { text: cow, .. } in text_masks.drain(..) {
if let Cow::Owned(s) = cow {
return_string_to_pool(s);
}
}
let empty: ProcessedTextMasks<'static> = unsafe { std::mem::transmute(text_masks) };
let mut state = TRANSFORM_STATE.borrow_mut();
if state.masks_pool.len() < MASKS_POOL_MAX {
state.masks_pool.push(empty);
}
}