use crate::node_types::rust_names::PrevNodeRustNames;
use crate::{NodeName, NodeRustNames};
use serde::Deserialize;
use std::borrow::{Borrow, Cow};
use std::collections::{BTreeMap, BTreeSet};
use std::fmt::Display;
use std::ops::{BitOrAssign, Index};
use std::path::{Path, PathBuf};
use crate::vec_set::VecSet;
use super::deserialize_json_array_as_stream::iter_json_array;
#[derive(Debug)]
pub struct NodeTypeMap {
nodes: BTreeMap<NodeName, NodeType>,
prev_rust_names: PrevNodeRustNames
}
#[derive(Clone, Debug)]
pub struct NodeType {
pub name: NodeName,
pub kind: NodeTypeKind,
pub(crate) rust_names: NodeRustNames,
}
#[derive(Clone, Debug, Deserialize)]
pub(crate) struct ContextFreeNodeType {
#[serde(flatten)]
name: NodeName,
#[serde(flatten)]
kind: NodeTypeKind,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum NodeTypeKind {
Supertype { subtypes: BTreeSet<NodeName> },
Regular {
#[serde(default)]
fields: BTreeMap<String, Children>,
#[serde(default)]
children: Children,
},
}
#[derive(Clone, Debug, Deserialize)]
pub struct Children {
pub multiple: bool,
pub required: bool,
pub types: VecSet<NodeName>,
}
impl NodeTypeMap {
pub(crate) fn new(node_types: Vec<ContextFreeNodeType>) -> Self {
let mut prev_rust_names = PrevNodeRustNames::new();
let nodes = node_types.into_iter()
.map(|node_type| (node_type.name.clone(), NodeType::new(node_type, &mut prev_rust_names)))
.collect();
Self { nodes, prev_rust_names }
}
pub fn get<Q: Ord + ?Sized>(&self, name: &Q) -> Option<&NodeType> where NodeName: Borrow<Q> {
self.nodes.get(name)
}
pub fn values(&self) -> impl Iterator<Item = &NodeType> {
self.nodes.values()
}
pub fn add_custom_supertype(&mut self, name: &str, subtypes: impl IntoIterator<Item=NodeName>)
-> Result<NodeName, NodeName>
{
if !name.starts_with("_") {
panic!("Illegal supertype name '{name}'. Supertypes must start with an underscore, i.e. '_{name}'.");
}
let subtypes = BTreeSet::from_iter(subtypes);
let subtypes_vecset = VecSet::from_iter(subtypes.clone());
let name = NodeName {
sexp_name: name.to_owned(),
is_named: true,
};
let new_node = ContextFreeNodeType {
name: name.clone(),
kind: NodeTypeKind::Supertype { subtypes },
};
let new_node = NodeType::new(new_node, &mut self.prev_rust_names);
if self.nodes.contains_key(&name) {
return Err(name);
}
self.nodes.insert(name.clone(), new_node);
for node in self.nodes.values_mut() {
match &mut node.kind {
NodeTypeKind::Regular { fields, children, .. } => {
for children in fields.values_mut().chain(std::iter::once(children)) {
if children.types == subtypes_vecset {
children.types = VecSet::from_iter([name.clone()]);
}
}
}
NodeTypeKind::Supertype { .. } => {}
}
}
Ok(name)
}
}
impl TryFrom<&Path> for NodeTypeMap {
type Error = crate::Error;
fn try_from(path: &Path) -> Result<Self, Self::Error> {
let text = std::fs::read_to_string(path)?;
NodeTypeMap::try_from(text.as_str())
}
}
impl TryFrom<PathBuf> for NodeTypeMap {
type Error = crate::Error;
fn try_from(value: PathBuf) -> Result<Self, Self::Error> {
Self::try_from(value.as_path())
}
}
impl TryFrom<&str> for NodeTypeMap {
type Error = crate::Error;
fn try_from(text: &str) -> Result<Self, Self::Error> {
let elems = iter_json_array::<ContextFreeNodeType, _>(text.as_bytes())
.collect::<Result<Vec<_>, _>>()?;
Ok(NodeTypeMap::new(elems))
}
}
impl<Q: Ord + ?Sized> Index<&Q> for NodeTypeMap where NodeName: Borrow<Q> {
type Output = NodeType;
fn index(&self, name: &Q) -> &Self::Output {
&self.nodes[name]
}
}
impl NodeType {
fn new(
ContextFreeNodeType { name, kind }: ContextFreeNodeType,
prev_rust_names: &mut PrevNodeRustNames,
) -> Self {
let rust_names = NodeRustNames::new(&name, prev_rust_names);
Self {
name,
rust_names,
kind,
}
}
pub fn rust_type_path(&self) -> Cow<'_, str> {
self.rust_names.type_path()
}
pub fn anon_union_type_name<'a>(
types: impl IntoIterator<Item = &'a NodeType, IntoIter: 'a>,
) -> impl Display + 'a {
NodeRustNames::anon_union_type_name(types.into_iter().map(|t| &t.rust_names))
}
pub fn field(&self, name: &str) -> Option<&Children> {
match &self.kind {
NodeTypeKind::Supertype { .. } => None,
NodeTypeKind::Regular { fields, .. } => fields.get(name),
}
}
}
impl Index<&str> for NodeType {
type Output = Children;
fn index(&self, name: &str) -> &Self::Output {
self.field(&name).expect("this node doesn't have a field with the given name")
}
}
impl Children {
pub const EMPTY: Self = Self { multiple: false, required: false, types: VecSet::new() };
pub fn is_empty(&self) -> bool {
self.types.is_empty()
}
}
impl Default for Children {
fn default() -> Self {
Self::EMPTY.clone()
}
}
impl BitOrAssign for Children {
fn bitor_assign(&mut self, other: Self) {
if other.is_empty() {
return;
} else if self.is_empty() {
*self = other;
return;
}
self.required |= other.required;
self.multiple |= other.multiple;
self.types.extend(other.types);
}
}