use gpui::Pixels;
use std::{
collections::{HashMap, VecDeque},
sync::Arc,
};
#[derive(Default)]
pub(super) struct WidthMeasurements {
widths: HashMap<Arc<str>, Pixels>,
order: VecDeque<Arc<str>>,
text_bytes: usize,
}
impl WidthMeasurements {
pub(super) fn measure(&mut self, text: &str, measure: impl FnOnce() -> Pixels) -> Pixels {
const MAX_ENTRIES: usize = 32_768;
const MAX_TEXT_BYTES: usize = 4 * 1024 * 1024;
if let Some(width) = self.widths.get(text) {
return *width;
}
let width = measure();
if text.len() > MAX_TEXT_BYTES {
return width;
}
while self.widths.len() >= MAX_ENTRIES || self.text_bytes + text.len() > MAX_TEXT_BYTES {
let Some(expired) = self.order.pop_front() else {
break;
};
self.text_bytes -= expired.len();
self.widths.remove(&expired);
}
let key: Arc<str> = text.into();
self.text_bytes += key.len();
self.order.push_back(key.clone());
self.widths.insert(key, width);
width
}
pub(super) fn clear(&mut self) {
self.widths.clear();
self.order.clear();
self.text_bytes = 0;
}
}