use crate::maps::{
var_types::EncodedVar,
ErasedMapElement,
LookupTable,
MapAttribute,
RawMapElement,
ResolvableString,
};
pub struct MapEncoder<'a> {
pub lookup: &'a mut LookupTable,
pub(crate) element_name: ResolvableString,
pub(crate) children: Vec<RawMapElement>,
pub(crate) attrs: Vec<MapAttribute>,
}
impl<'a> MapEncoder<'a> {
pub fn name(&mut self, name: impl AsRef<str>) {
self.element_name = self.lookup.index_string(name);
}
pub fn attribute(&mut self, name: impl AsRef<str>, value: impl Into<EncodedVar>) {
self.attrs
.push(MapAttribute::new(self.lookup.index_string(name), value))
}
pub fn optional_attribute<'c, T: Into<EncodedVar> + Clone + 'c>(
&mut self,
name: impl AsRef<str>,
value: &Option<T>,
) {
if let Some(t) = value {
self.attribute(name, t.clone())
}
}
pub fn child<T: ErasedMapElement>(&mut self, child: &T) {
let child_name = self.lookup.index_string(child.name());
let mut fork = self.fork(child_name);
child.to_raw(&mut fork);
let child = fork.resolve();
self.children.push(child);
}
pub fn children<T: ErasedMapElement>(&mut self, children: impl AsRef<[T]>) {
let children = children.as_ref();
for child in children {
self.child(child)
}
}
#[doc(hidden)]
pub fn fork(&mut self, name: ResolvableString) -> MapEncoder {
MapEncoder {
lookup: self.lookup,
element_name: name,
children: Vec::new(),
attrs: Vec::new(),
}
}
pub fn resolve(self) -> RawMapElement {
RawMapElement {
name: self.element_name,
attributes: self.attrs,
children: self.children,
}
}
#[doc(hidden)]
pub fn from_raw(&mut self, raw: &RawMapElement) {
self.element_name = raw.name.clone();
self.attrs.clone_from(&raw.attributes);
self.children.clone_from(&raw.children);
}
}