use std::collections::HashMap;
use std::sync::Arc;
use weaver_lang::CompiledTemplate;
use crate::lorebook::BookId;
pub type EntryTemplates = HashMap<String, Arc<CompiledTemplate>>;
#[derive(Default)]
pub struct BookTemplates {
books: Vec<EntryTemplates>,
}
impl BookTemplates {
pub fn new() -> Self {
Self { books: Vec::new() }
}
pub fn push(&mut self, templates: EntryTemplates) -> BookId {
let id = BookId(self.books.len());
self.books.push(templates);
id
}
pub fn len(&self) -> usize {
self.books.len()
}
pub fn is_empty(&self) -> bool {
self.books.is_empty()
}
pub fn get(&self, book: BookId, id: &str) -> Option<&Arc<CompiledTemplate>> {
self.books.get(book.0)?.get(id)
}
pub fn iter_except(
&self,
exclude: Option<BookId>,
) -> impl Iterator<Item = (BookId, &EntryTemplates)> {
self.books
.iter()
.enumerate()
.map(|(i, m)| (BookId(i), m))
.filter(move |(b, _)| Some(*b) != exclude)
}
}
pub struct ResolvedRef<'a> {
pub book: BookId,
pub template: &'a Arc<CompiledTemplate>,
}
pub trait IdResolver: Send + Sync {
fn resolve<'a>(
&self,
id: &str,
origin: Option<BookId>,
books: &'a BookTemplates,
) -> Option<ResolvedRef<'a>>;
}
#[derive(Debug, Default, Clone, Copy)]
pub struct DefaultIdResolver;
impl IdResolver for DefaultIdResolver {
fn resolve<'a>(
&self,
id: &str,
origin: Option<BookId>,
books: &'a BookTemplates,
) -> Option<ResolvedRef<'a>> {
if let Some(origin) = origin {
if let Some(template) = books.get(origin, id) {
return Some(ResolvedRef {
book: origin,
template,
});
}
}
books
.iter_except(origin)
.find_map(|(book, map)| map.get(id).map(|template| ResolvedRef { book, template }))
}
}