use memchr::memchr_iter;
use nucleo::{Item, Snapshot, Utf32Str};
use super::VariableSizeBuffer;
use crate::Render;
impl<T: Send + Sync + 'static> VariableSizeBuffer for Snapshot<T> {
type Cursor = u32;
type Item<'a>
= Item<'a, T>
where
Self: 'a;
fn count(&self) -> u32 {
self.matched_item_count()
}
fn size(item: &Self::Item<'_>) -> usize {
let num_linebreaks = match item.matcher_columns[0].slice(..) {
Utf32Str::Ascii(bytes) => memchr_iter(b'\n', bytes).count(),
Utf32Str::Unicode(chars) => {
chars
.iter()
.filter(|ch| **ch == '\n' || **ch == '\r')
.count()
}
};
1 + num_linebreaks
}
fn before(&self, selection: Self::Cursor) -> impl DoubleEndedIterator<Item = Self::Item<'_>> {
self.matched_items(..=selection).rev()
}
fn after(&self, selection: Self::Cursor) -> impl DoubleEndedIterator<Item = Self::Item<'_>> {
self.matched_items(selection..).skip(1)
}
}
pub enum RenderedItem<'a, S> {
Ascii(&'a str),
Unicode(S),
}
impl<'a, S> RenderedItem<'a, S> {
pub fn new<T, R>(item: &Item<'a, T>, renderer: &R) -> Self
where
R: Render<T, Str<'a> = S>,
{
if let Utf32Str::Ascii(bytes) = item.matcher_columns[0].slice(..) {
RenderedItem::Ascii(unsafe { std::str::from_utf8_unchecked(bytes) })
} else {
RenderedItem::Unicode(renderer.render(item.data))
}
}
}
impl<S: AsRef<str>> AsRef<str> for RenderedItem<'_, S> {
fn as_ref(&self) -> &str {
match self {
RenderedItem::Ascii(s) => s,
RenderedItem::Unicode(u) => u.as_ref(),
}
}
}