use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Direction {
TD,
LR,
RL,
BT,
}
impl Default for Direction {
fn default() -> Self {
Direction::TD
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Shape {
Rect,
Rounded,
Stadium,
Diamond,
Circle,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EdgeKind {
Arrow,
Open,
Dotted,
Thick,
}
#[derive(Debug, Clone)]
pub struct Node {
pub id: String,
pub label: String,
pub shape: Shape,
}
#[derive(Debug, Clone)]
pub struct Edge {
pub from: usize,
pub to: usize,
pub label: Option<String>,
pub kind: EdgeKind,
}
#[derive(Debug, Default)]
pub struct Graph {
pub direction: Direction,
pub nodes: Vec<Node>,
pub edges: Vec<Edge>,
index: HashMap<String, usize>,
}
impl Graph {
pub fn ensure_node(&mut self, id: &str, label: Option<String>, shape: Option<Shape>) -> usize {
if let Some(&i) = self.index.get(id) {
if let Some(l) = label {
self.nodes[i].label = l;
}
if let Some(s) = shape {
self.nodes[i].shape = s;
}
i
} else {
let i = self.nodes.len();
self.nodes.push(Node {
id: id.to_string(),
label: label.unwrap_or_else(|| id.to_string()),
shape: shape.unwrap_or(Shape::Rect),
});
self.index.insert(id.to_string(), i);
i
}
}
pub fn add_edge(&mut self, from: usize, to: usize, label: Option<String>, kind: EdgeKind) {
self.edges.push(Edge {
from,
to,
label,
kind,
});
}
}
#[derive(Debug)]
pub enum Document {
Flowchart(Graph),
Er(ErDiagram),
}
#[derive(Debug, Default)]
pub struct ErDiagram {
pub entities: Vec<Entity>,
pub relations: Vec<Relation>,
index: HashMap<String, usize>,
}
impl ErDiagram {
pub fn ensure_entity(&mut self, name: &str) -> usize {
if let Some(&i) = self.index.get(name) {
i
} else {
let i = self.entities.len();
self.entities.push(Entity {
name: name.to_string(),
attrs: Vec::new(),
});
self.index.insert(name.to_string(), i);
i
}
}
}
#[derive(Debug)]
pub struct Entity {
pub name: String,
pub attrs: Vec<Attr>,
}
#[derive(Debug)]
pub struct Attr {
pub ty: String,
pub name: String,
pub keys: Vec<Key>,
pub comment: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Key {
Pk,
Fk,
Uk,
}
impl Key {
pub fn tag(self) -> &'static str {
match self {
Key::Pk => "PK",
Key::Fk => "FK",
Key::Uk => "UK",
}
}
}
#[derive(Debug)]
pub struct Relation {
pub from: usize,
pub to: usize,
pub card_from: Card,
pub card_to: Card,
pub identifying: bool,
pub label: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Card {
One,
ZeroOne,
ZeroMany,
OneMany,
}