use crate::ig::docs::Doc;
use crate::ig::node::Node;
use crate::ig::symbols::{Symbol, SymbolMap, SymbolTable};
use std::sync::Mutex;
#[derive(Default)]
pub struct DocBuilder {
symbols: Mutex<SymbolTable>,
}
impl DocBuilder {
pub fn new() -> Self {
DocBuilder {
symbols: Mutex::new(SymbolTable::new()),
}
}
pub fn resolve(&self, symbol: impl AsRef<str>) -> anyhow::Result<Symbol> {
let mut guard = self.symbols.lock().unwrap();
guard.find_or_create(symbol)
}
pub fn obj(&'_ self) -> ObjectBuilder<'_> {
ObjectBuilder {
doc_builder: self,
map: SymbolMap::new(),
}
}
pub fn list(&self) -> ListBuilder {
ListBuilder { list: Vec::new() }
}
pub fn build_object(&self, obj: ObjectBuilder) -> Doc {
Doc::new(self.symbols.lock().unwrap().clone(), Node::Object(obj.map))
}
pub fn build_list(&self, list: ListBuilder) -> Doc {
Doc::new(self.symbols.lock().unwrap().clone(), Node::List(list.list))
}
}
pub struct ObjectBuilder<'a> {
doc_builder: &'a DocBuilder,
map: SymbolMap<Node>,
}
impl ObjectBuilder<'_> {
pub fn put_int(&mut self, key: impl AsRef<str>, value: i64) -> anyhow::Result<()> {
let symbol = self.doc_builder.resolve(key)?;
self.insert_int(symbol, value);
Ok(())
}
pub fn insert_int(&mut self, key: Symbol, value: i64) {
self.map.put(key, Node::Integer(value));
}
pub fn put_string(
&mut self,
key: impl AsRef<str>,
value: impl AsRef<str>,
) -> anyhow::Result<()> {
let symbol = self.doc_builder.resolve(key)?;
self.insert_string(symbol, value);
Ok(())
}
pub fn insert_string(&mut self, key: Symbol, value: impl AsRef<str>) {
self.map.put(key, Node::from(value.as_ref()));
}
pub fn put_bool(&mut self, key: impl AsRef<str>, value: bool) -> anyhow::Result<()> {
let symbol = self.doc_builder.resolve(key)?;
self.insert_bool(symbol, value);
Ok(())
}
pub fn insert_bool(&mut self, key: Symbol, value: bool) {
self.map.put(key, Node::Boolean(value));
}
pub fn put_list(&mut self, key: impl AsRef<str>, list: ListBuilder) -> anyhow::Result<()> {
let symbol = self.doc_builder.resolve(key)?;
self.insert_list(symbol, list);
Ok(())
}
pub fn insert_list(&mut self, key: Symbol, list: ListBuilder) {
self.map.put(key, Node::List(list.list));
}
pub fn put_object(&mut self, key: impl AsRef<str>, obj: ObjectBuilder) -> anyhow::Result<()> {
let symbol = self.doc_builder.resolve(key)?;
self.insert_object(symbol, obj);
Ok(())
}
pub fn insert_object(&mut self, key: Symbol, obj: ObjectBuilder) {
self.map.put(key, Node::Object(obj.map));
}
}
pub struct ListBuilder {
list: Vec<Node>,
}
impl ListBuilder {
pub fn append_int(&mut self, value: i64) {
self.list.push(Node::Integer(value));
}
pub fn append_string(&mut self, value: impl AsRef<str>) {
self.list.push(Node::from(value.as_ref()));
}
pub fn append_bool(&mut self, value: bool) {
self.list.push(Node::Boolean(value));
}
pub fn append_list(&mut self, list: ListBuilder) {
self.list.push(Node::List(list.list));
}
pub fn append_object(&mut self, obj: ObjectBuilder) {
self.list.push(Node::Object(obj.map));
}
}