magnetar/src/model/map_type.rs

164 lines
4.4 KiB
Rust

use crate::model::LinkIdent;
use std::any::TypeId;
use std::fmt::Debug;
use std::sync::Arc;
type PMT = PackMapType;
#[derive(Clone, Debug)]
pub struct Multi(Vec<Arc<PMT>>);
impl Multi {
pub fn get_base(&self) -> Option<&PMT> {
for pmt in &self.0 {
match pmt.as_ref() {
PackMapType::FromType(CommandPackFromType { base: true, .. }) => return Some(pmt),
PackMapType::Maybe(CommandPackMaybe { inner }) => {
if let PackMapType::FromType(..) = inner.as_ref() {
return Some(pmt);
}
}
PackMapType::Multi(CommandPackMulti { inner }) => {
if let Some(pmt) = inner.get_base() {
return Some(pmt);
}
}
_ => {}
}
}
None
}
}
impl From<Vec<PMT>> for Multi {
fn from(v: Vec<PMT>) -> Self {
Multi(v.into_iter().map(Arc::new).collect())
}
}
#[derive(Clone, Debug)]
pub enum PackMapType {
FromType(CommandPackFromType),
Maybe(CommandPackMaybe),
Child(CommandPackChild),
Aggregate(CommandPackAggregate),
Multi(CommandPackMulti),
}
trait PackCommand {}
#[derive(Clone, Debug)]
pub struct CommandPackFromType {
pub name: String,
pub id: TypeId,
pub base: bool,
}
impl PackCommand for CommandPackFromType {}
#[derive(Clone, Debug)]
pub struct CommandPackMaybe {
pub inner: Arc<PackMapType>,
}
impl PackCommand for CommandPackMaybe {}
#[derive(Clone, Debug)]
pub struct CommandPackChild {
pub inner: Arc<PackMapType>,
pub link: LinkIdent,
}
impl PackCommand for CommandPackChild {}
#[derive(Clone, Debug)]
pub struct CommandPackAggregate {
pub inner: Arc<PackMapType>,
}
impl PackCommand for CommandPackAggregate {}
#[derive(Clone, Debug)]
pub struct CommandPackMulti {
pub inner: Multi,
}
impl PackCommand for CommandPackMulti {}
impl PackMapType {
pub fn from_type<T: Sized + 'static>(base: bool) -> Self {
PackMapType::FromType(CommandPackFromType {
name: std::any::type_name::<T>().to_string(),
id: TypeId::of::<T>(),
base,
})
}
pub fn get_base_type(&self) -> TypeId {
let id = match self {
PackMapType::FromType(CommandPackFromType { base: true, .. }) => Some(self),
PackMapType::Multi(CommandPackMulti { inner }) => inner.get_base(),
_ => None,
};
let PackMapType::FromType(CommandPackFromType { id, .. }) = id.expect("no base type") else {
panic!("base type is not FromType")
};
*id
}
pub fn as_edges(
&self,
base_parent: &Option<(usize, String)>,
parent: &Option<(usize, String)>,
level: usize,
) -> Vec<(Option<String>, String)> {
match self {
PackMapType::FromType(CommandPackFromType {
name, base: true, ..
}) => {
vec![(base_parent.clone().map(|(_, s)| s), name.clone())]
}
PackMapType::FromType(CommandPackFromType {
name, base: false, ..
}) => {
vec![(parent.clone().map(|(_, s)| s), name.clone())]
}
PackMapType::Maybe(CommandPackMaybe { inner }) => {
inner.as_edges(base_parent, parent, level)
}
PackMapType::Aggregate(CommandPackAggregate { inner }) => {
inner.as_edges(base_parent, parent, level)
}
PackMapType::Child(CommandPackChild { inner, .. }) => {
inner.as_edges(parent, &None, level + 1)
}
PackMapType::Multi(CommandPackMulti { inner }) => {
let new_parent = if let Some(PackMapType::FromType(CommandPackFromType {
name,
base: true,
..
})) = inner.get_base()
{
if parent.clone().is_some_and(|(l, _)| l == level) {
parent.clone()
} else {
Some((level, name.clone()))
}
} else {
parent.clone()
};
let mut edges = Vec::new();
for t in &inner.0 {
edges.extend(t.as_edges(base_parent, &new_parent, level));
}
edges
}
}
}
}