use alloc::collections::BTreeMap;
use alloc::vec::Vec;
#[derive(Debug)]
pub struct DatDocument<'a> {
pub(crate) document: BTreeMap<&'a str, Vec<EntryFragment<'a>>>,
}
impl<'a> DatDocument<'a> {
pub fn entry(&self, key: &'a str) -> Option<impl Iterator<Item = &EntryFragment<'a>>> {
self.document.get(key).map(|f| f.iter())
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct SubEntry<'a> {
pub(crate) keys: BTreeMap<&'a str, &'a str>,
}
impl<'a> SubEntry<'a> {
pub fn get(&'a self, key: &str) -> Option<&'a str> {
self.keys.get(key).map(|&f| f)
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum EntryData<'a> {
Scalar(&'a str),
SubEntry(SubEntry<'a>),
}
#[derive(Debug, Eq, PartialEq)]
pub enum EntryNode<'a> {
Unique(EntryData<'a>),
Many(Vec<EntryData<'a>>),
}
impl<'a> EntryNode<'a> {
pub fn iter(&'a self) -> impl Iterator<Item = &EntryData> {
return EntryIter {
node: self,
dead: false,
multi_idx: 0,
};
}
pub fn unique(&'a self) -> &EntryData {
match self {
EntryNode::Unique(entry) => entry,
EntryNode::Many(entries) => entries.first().unwrap(),
}
}
}
#[derive(Debug)]
pub struct EntryFragment<'a> {
keys: BTreeMap<&'a str, EntryNode<'a>>,
}
impl<'a> EntryFragment<'a> {
#[doc(hidden)]
pub(crate) fn new(keys: BTreeMap<&'a str, EntryNode<'a>>) -> Self {
EntryFragment { keys }
}
pub fn entry(&'a self, key: &str) -> Option<&'a EntryNode<'a>> {
self.keys.get(key)
}
pub fn unique(&'a self, key: &str) -> Option<&'a EntryData> {
self.keys.get(key).map(|f| f.unique())
}
pub fn iter(&'a self, key: &str) -> Option<impl Iterator<Item = &'a EntryData>> {
self.keys.get(key).map(|f| f.iter())
}
}
struct EntryIter<'a> {
node: &'a EntryNode<'a>,
dead: bool,
multi_idx: usize,
}
impl<'a> Iterator for EntryIter<'a> {
type Item = &'a EntryData<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.dead {
return None;
}
match self.node {
EntryNode::Unique(entry) => {
self.dead = true;
return Some(entry);
}
EntryNode::Many(vec) => {
let get = vec.get(self.multi_idx);
self.multi_idx += 1;
if get.is_none() {
self.dead = true;
}
get
}
}
}
}