use super::{
parser,
store::{
CacheSink, DefaultCacheStore, DefaultNodeStore, DefaultValueStore, NodeData, NodeId,
ValueData, ValueId,
},
RegisterDescription, ValueCtxt,
};
#[derive(Default)]
pub struct GenApiBuilder<T = DefaultNodeStore, U = DefaultValueStore, S = DefaultCacheStore> {
node_store: T,
value_store: U,
cache_store: S,
}
pub type BuildResult<T, U, S> = parser::ParseResult<(RegisterDescription, T, ValueCtxt<U, S>)>;
impl<T, U, S> GenApiBuilder<T, U, S> {
pub fn build(mut self, xml: &impl AsRef<str>) -> BuildResult<T::Store, U::Store, S::Store>
where
T: NodeStoreBuilder,
U: ValueStoreBuilder,
S: CacheStoreBuilder,
{
let reg_desc = parser::parse(
xml,
&mut self.node_store,
&mut self.value_store,
&mut self.cache_store,
)?;
Ok((
reg_desc,
self.node_store.build(),
ValueCtxt::new(self.value_store.build(), self.cache_store.build()),
))
}
pub fn no_cache(self) -> GenApiBuilder<T, U, CacheSink> {
GenApiBuilder {
node_store: self.node_store,
value_store: self.value_store,
cache_store: CacheSink::default(),
}
}
pub fn with_node_store<T2>(self, node_store: T2) -> GenApiBuilder<T2, U, S> {
GenApiBuilder {
node_store,
value_store: self.value_store,
cache_store: self.cache_store,
}
}
pub fn with_value_store<U2>(self, value_store: U2) -> GenApiBuilder<T, U2, S> {
GenApiBuilder {
node_store: self.node_store,
value_store,
cache_store: self.cache_store,
}
}
pub fn with_cache_store<S2>(self, cache_store: S2) -> GenApiBuilder<T, U, S2> {
GenApiBuilder {
node_store: self.node_store,
value_store: self.value_store,
cache_store,
}
}
}
pub trait NodeStoreBuilder {
type Store;
fn build(self) -> Self::Store;
fn store_node(&mut self, nid: NodeId, data: NodeData);
fn get_or_intern<T>(&mut self, node_name: T) -> NodeId
where
T: AsRef<str>;
fn fresh_id(&mut self) -> u32;
}
pub trait ValueStoreBuilder {
type Store;
fn build(self) -> Self::Store;
fn store<T, U>(&mut self, data: T) -> U
where
T: Into<ValueData>,
U: From<ValueId>;
}
pub trait CacheStoreBuilder {
type Store;
fn build(self) -> Self::Store;
fn store_invalidator(&mut self, invalidator: NodeId, target: NodeId);
}