164 lines
4.4 KiB
Rust
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
|
|
}
|
|
}
|
|
}
|
|
}
|