use crate::de::{GroupDeserializer, GroupRefDeserializer};
use crate::error::NamelistError;
use crate::formatter::NamelistFormatter;
use crate::parser::Parser;
use crate::ser::GroupSerializer;
use crate::Result;
use std::{collections::BTreeMap, str::FromStr};
mod array;
mod item;
mod literal_constant;
pub type Map<K, V> = std::collections::BTreeMap<K, V>;
pub type MapIter<'a, K, V> = std::collections::btree_map::Iter<'a, K, V>;
pub type MapIntoIter<K, V> = std::collections::btree_map::IntoIter<K, V>;
pub(crate) use array::{Array, ArrayIter, ArrayRefIter, ItemRef};
pub(crate) use item::Item;
pub(crate) use literal_constant::LiteralConstant;
#[derive(Clone, Debug)]
pub struct NamelistGroup {
pub(crate) group_name: String,
pub(crate) items: Map<String, Item>,
}
impl NamelistGroup {
pub fn new(group_name: impl Into<String>, items: Map<String, Item>) -> NamelistGroup {
NamelistGroup {
group_name: group_name.into(),
items,
}
}
}
impl std::ops::Deref for NamelistGroup {
type Target = Map<String, Item>;
fn deref(&self) -> &Self::Target {
&self.items
}
}
impl FromStr for NamelistGroup {
type Err = NamelistError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
Parser::new(s).parse()
}
}
impl std::fmt::Display for NamelistGroup {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
NamelistFormatter::new().fmt_namelist(self, f)
}
}
pub fn group_from_str<T>(s: &str) -> Result<(String, T)>
where
T: serde::de::DeserializeOwned,
{
let group = NamelistGroup::from_str(s)?;
Ok((
group.group_name.clone(),
T::deserialize(GroupDeserializer::new(group))?,
))
}
pub fn group_to_string<T>(group_name: &str, value: &T) -> Result<String>
where
T: serde::ser::Serialize,
{
value
.serialize(GroupSerializer::new(group_name))
.map(|nml| format!("{nml}"))
}
pub struct NamelistInput(BTreeMap<String, Vec<NamelistGroup>>);
impl NamelistInput {
pub fn try_from_str(input: &str) -> Result<Self> {
Self::try_from_parser(Parser::new(input))
}
fn try_from_parser(parser: Parser) -> Result<Self> {
let mut map: BTreeMap<String, Vec<NamelistGroup>> = BTreeMap::new();
for group in parser {
let group = group?;
map.entry(group.group_name.clone())
.and_modify(|n| n.push(group.clone()))
.or_insert_with(|| vec![group]);
}
Ok(NamelistInput(map))
}
pub fn take_groups(&mut self, group_name: &str) -> impl Iterator<Item = GroupDeserializer> {
self.0
.remove(group_name)
.into_iter()
.flatten()
.map(|namelist_group| GroupDeserializer::new(namelist_group))
}
pub fn groups(&self, group_name: &str) -> impl Iterator<Item = GroupRefDeserializer> {
self.0
.get(group_name)
.into_iter()
.flatten()
.map(|namelist_group| GroupRefDeserializer::new(namelist_group))
}
}
impl IntoIterator for NamelistInput {
type IntoIter = Box<dyn Iterator<Item = GroupDeserializer>>;
type Item = GroupDeserializer;
fn into_iter(self) -> Self::IntoIter {
Box::new(
self.0
.into_iter()
.map(|(_, v)| v.into_iter().map(|group| GroupDeserializer::new(group)))
.flatten(),
)
}
}
impl<'a> IntoIterator for &'a NamelistInput {
type IntoIter = Box<dyn Iterator<Item = GroupRefDeserializer<'a>> + 'a>;
type Item = GroupRefDeserializer<'a>;
fn into_iter(self) -> Self::IntoIter {
Box::new(
self.0
.iter()
.map(|(_, v)| v.iter().map(|group| GroupRefDeserializer::new(group)))
.flatten(),
)
}
}