use std::collections::HashMap;
use panproto_gat::Name;
use serde::{Deserialize, Serialize};
use smallvec::SmallVec;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Vertex {
pub id: Name,
pub kind: Name,
pub nsid: Option<Name>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Edge {
pub src: Name,
pub tgt: Name,
pub kind: Name,
pub name: Option<Name>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct HyperEdge {
pub id: Name,
pub kind: Name,
pub signature: HashMap<Name, Name>,
pub parent_label: Name,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Constraint {
pub sort: Name,
pub value: String,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Variant {
pub id: Name,
pub parent_vertex: Name,
pub tag: Option<Name>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Ordering {
pub edge: Edge,
pub position: u32,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct RecursionPoint {
pub mu_id: Name,
pub target_vertex: Name,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Span {
pub id: Name,
pub left: Name,
pub right: Name,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub enum UsageMode {
#[default]
Structural,
Linear,
Affine,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct CoercionSpec {
pub forward: panproto_expr::Expr,
pub inverse: Option<panproto_expr::Expr>,
pub class: panproto_gat::CoercionClass,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Schema {
pub protocol: String,
pub vertices: HashMap<Name, Vertex>,
#[serde(with = "crate::serde_helpers::map_as_vec")]
pub edges: HashMap<Edge, Name>,
pub hyper_edges: HashMap<Name, HyperEdge>,
pub constraints: HashMap<Name, Vec<Constraint>>,
pub required: HashMap<Name, Vec<Edge>>,
pub nsids: HashMap<Name, Name>,
#[serde(default)]
pub variants: HashMap<Name, Vec<Variant>>,
#[serde(default, with = "crate::serde_helpers::map_as_vec_default")]
pub orderings: HashMap<Edge, u32>,
#[serde(default)]
pub recursion_points: HashMap<Name, RecursionPoint>,
#[serde(default)]
pub spans: HashMap<Name, Span>,
#[serde(default, with = "crate::serde_helpers::map_as_vec_default")]
pub usage_modes: HashMap<Edge, UsageMode>,
#[serde(default)]
pub nominal: HashMap<Name, bool>,
#[serde(default, with = "crate::serde_helpers::map_as_vec_default")]
pub coercions: HashMap<(Name, Name), CoercionSpec>,
#[serde(default)]
pub mergers: HashMap<Name, panproto_expr::Expr>,
#[serde(default)]
pub defaults: HashMap<Name, panproto_expr::Expr>,
#[serde(default)]
pub policies: HashMap<Name, panproto_expr::Expr>,
pub outgoing: HashMap<Name, SmallVec<Edge, 4>>,
pub incoming: HashMap<Name, SmallVec<Edge, 4>>,
#[serde(with = "crate::serde_helpers::map_as_vec")]
pub between: HashMap<(Name, Name), SmallVec<Edge, 2>>,
}
impl Schema {
#[must_use]
pub fn vertex(&self, id: &str) -> Option<&Vertex> {
self.vertices.get(id)
}
#[must_use]
pub fn outgoing_edges(&self, vertex_id: &str) -> &[Edge] {
self.outgoing.get(vertex_id).map_or(&[], SmallVec::as_slice)
}
#[must_use]
pub fn incoming_edges(&self, vertex_id: &str) -> &[Edge] {
self.incoming.get(vertex_id).map_or(&[], SmallVec::as_slice)
}
#[must_use]
#[inline]
pub fn edges_between(&self, src: &str, tgt: &str) -> &[Edge] {
self.between
.get(&(Name::from(src), Name::from(tgt)))
.map_or(&[], SmallVec::as_slice)
}
#[must_use]
#[inline]
pub fn has_vertex(&self, id: &str) -> bool {
self.vertices.contains_key(id)
}
#[must_use]
pub fn vertex_count(&self) -> usize {
self.vertices.len()
}
#[must_use]
pub fn edge_count(&self) -> usize {
self.edges.len()
}
}