use unicode_segmentation::UnicodeSegmentation;
pub trait FileId: Eq + Clone {}
impl<T> FileId for T where T: Eq + Clone {}
pub trait Files<'a> {
type FileId: FileId;
type Content: 'a + AsRef<str>;
fn name(&self, id: &'a Self::FileId) -> Option<&'a str>;
fn content(&self, id: &'a Self::FileId) -> Option<Self::Content>;
fn line_from_char(&self, id: &'a Self::FileId, char: usize) -> Option<usize> {
self.content(id)?
.as_ref()
.graphemes(true)
.take(char)
.filter(|c| *c == "\n")
.count()
.checked_add(1)
}
fn char_from_line(&self, id: &'a Self::FileId, line: usize) -> Option<usize> {
Some(
self.content(id)?
.as_ref()
.lines()
.take(line - 1)
.map(|l| l.graphemes(true).count() + 1)
.sum::<usize>(),
)
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct NoFile;
impl PartialEq for NoFile {
fn eq(&self, _: &Self) -> bool {
true
}
}
impl Eq for NoFile {}
impl<'a> Files<'a> for NoFile {
type FileId = Self;
type Content = &'a str;
fn name(&self, _: &'a Self::FileId) -> Option<&'a str> {
None
}
fn content(&self, _: &'a Self::FileId) -> Option<Self::Content> {
None
}
}