use std::borrow::Borrow;
use std::collections::{BTreeMap, btree_map};
use std::iter::FusedIterator;
use std::ops::Index;
use serde::{Deserialize, Serialize};
use crate::core::ids::{
BindingId, EdgeId, GraphId, GroupId, NodeId, PortId, StickyNoteId, SymbolId,
};
use crate::core::imports::GraphImport;
use super::binding::Binding;
use super::edge::Edge;
use super::node::Node;
use super::port::Port;
use super::resources::{Group, StickyNote, Symbol};
pub const GRAPH_VERSION: u32 = 1;
#[derive(Debug, Clone, Copy)]
pub struct GraphElements<'a, K, V> {
entries: &'a BTreeMap<K, V>,
}
#[derive(Debug, Clone)]
pub struct GraphElementIter<'a, K, V> {
inner: btree_map::Iter<'a, K, V>,
}
#[derive(Debug, Clone)]
pub struct GraphElementKeys<'a, K, V> {
inner: btree_map::Keys<'a, K, V>,
}
#[derive(Debug, Clone)]
pub struct GraphElementValues<'a, K, V> {
inner: btree_map::Values<'a, K, V>,
}
impl<'a, K, V> GraphElements<'a, K, V> {
pub(crate) fn new(entries: &'a BTreeMap<K, V>) -> Self {
Self { entries }
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn contains_key<Q>(&self, key: &Q) -> bool
where
K: Borrow<Q> + Ord,
Q: Ord + ?Sized,
{
self.entries.contains_key(key)
}
pub fn get<Q>(&self, key: &Q) -> Option<&'a V>
where
K: Borrow<Q> + Ord,
Q: Ord + ?Sized,
{
self.entries.get(key)
}
pub fn iter(&self) -> GraphElementIter<'a, K, V> {
GraphElementIter {
inner: self.entries.iter(),
}
}
pub fn keys(&self) -> GraphElementKeys<'a, K, V> {
GraphElementKeys {
inner: self.entries.keys(),
}
}
pub fn values(&self) -> GraphElementValues<'a, K, V> {
GraphElementValues {
inner: self.entries.values(),
}
}
}
impl<'a, 'b, K, V> PartialEq<GraphElements<'b, K, V>> for GraphElements<'a, K, V>
where
K: Ord + PartialEq,
V: PartialEq,
{
fn eq(&self, other: &GraphElements<'b, K, V>) -> bool {
self.entries == other.entries
}
}
impl<'a, K, V> Eq for GraphElements<'a, K, V>
where
K: Ord + Eq,
V: Eq,
{
}
impl<'a, K, V> Index<&K> for GraphElements<'a, K, V>
where
K: Ord,
{
type Output = V;
fn index(&self, key: &K) -> &Self::Output {
self.entries.get(key).expect("no entry found for key")
}
}
impl<'a, K, V> IntoIterator for GraphElements<'a, K, V> {
type Item = (&'a K, &'a V);
type IntoIter = GraphElementIter<'a, K, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, K, V> Iterator for GraphElementIter<'a, K, V> {
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K, V> DoubleEndedIterator for GraphElementIter<'a, K, V> {
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back()
}
}
impl<'a, K, V> ExactSizeIterator for GraphElementIter<'a, K, V> {}
impl<'a, K, V> FusedIterator for GraphElementIter<'a, K, V> {}
impl<'a, K, V> Iterator for GraphElementKeys<'a, K, V> {
type Item = &'a K;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K, V> DoubleEndedIterator for GraphElementKeys<'a, K, V> {
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back()
}
}
impl<'a, K, V> ExactSizeIterator for GraphElementKeys<'a, K, V> {}
impl<'a, K, V> FusedIterator for GraphElementKeys<'a, K, V> {}
impl<'a, K, V> Iterator for GraphElementValues<'a, K, V> {
type Item = &'a V;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K, V> DoubleEndedIterator for GraphElementValues<'a, K, V> {
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back()
}
}
impl<'a, K, V> ExactSizeIterator for GraphElementValues<'a, K, V> {}
impl<'a, K, V> FusedIterator for GraphElementValues<'a, K, V> {}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Graph {
graph_id: GraphId,
graph_version: u32,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub(crate) imports: BTreeMap<GraphId, GraphImport>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub(crate) symbols: BTreeMap<SymbolId, Symbol>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub(crate) nodes: BTreeMap<NodeId, Node>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub(crate) ports: BTreeMap<PortId, Port>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub(crate) edges: BTreeMap<EdgeId, Edge>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub(crate) groups: BTreeMap<GroupId, Group>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub(crate) sticky_notes: BTreeMap<StickyNoteId, StickyNote>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub(crate) bindings: BTreeMap<BindingId, Binding>,
}
impl Default for Graph {
fn default() -> Self {
Self::new(GraphId::new())
}
}
impl Graph {
pub fn new(graph_id: GraphId) -> Self {
Self {
graph_id,
graph_version: GRAPH_VERSION,
imports: BTreeMap::new(),
symbols: BTreeMap::new(),
nodes: BTreeMap::new(),
ports: BTreeMap::new(),
edges: BTreeMap::new(),
groups: BTreeMap::new(),
sticky_notes: BTreeMap::new(),
bindings: BTreeMap::new(),
}
}
pub fn graph_id(&self) -> GraphId {
self.graph_id
}
pub fn graph_version(&self) -> u32 {
self.graph_version
}
pub fn imports(&self) -> GraphElements<'_, GraphId, GraphImport> {
GraphElements::new(&self.imports)
}
pub fn import(&self, id: &GraphId) -> Option<&GraphImport> {
self.imports.get(id)
}
pub(crate) fn import_mut(&mut self, id: &GraphId) -> Option<&mut GraphImport> {
self.imports.get_mut(id)
}
pub(crate) fn update_import<R>(
&mut self,
id: &GraphId,
f: impl FnOnce(&mut GraphImport) -> R,
) -> Option<R> {
self.imports.get_mut(id).map(f)
}
pub(crate) fn insert_import(&mut self, id: GraphId, value: GraphImport) -> Option<GraphImport> {
self.imports.insert(id, value)
}
pub(crate) fn remove_import(&mut self, id: &GraphId) -> Option<GraphImport> {
self.imports.remove(id)
}
pub(crate) fn clear_imports(&mut self) {
self.imports.clear();
}
pub(crate) fn retain_imports(&mut self, f: impl FnMut(&GraphId, &mut GraphImport) -> bool) {
self.imports.retain(f);
}
pub fn symbols(&self) -> GraphElements<'_, SymbolId, Symbol> {
GraphElements::new(&self.symbols)
}
pub fn symbol(&self, id: &SymbolId) -> Option<&Symbol> {
self.symbols.get(id)
}
pub(crate) fn symbol_mut(&mut self, id: &SymbolId) -> Option<&mut Symbol> {
self.symbols.get_mut(id)
}
pub(crate) fn update_symbol<R>(
&mut self,
id: &SymbolId,
f: impl FnOnce(&mut Symbol) -> R,
) -> Option<R> {
self.symbols.get_mut(id).map(f)
}
pub(crate) fn insert_symbol(&mut self, id: SymbolId, value: Symbol) -> Option<Symbol> {
self.symbols.insert(id, value)
}
pub(crate) fn remove_symbol(&mut self, id: &SymbolId) -> Option<Symbol> {
self.symbols.remove(id)
}
pub(crate) fn clear_symbols(&mut self) {
self.symbols.clear();
}
pub(crate) fn retain_symbols(&mut self, f: impl FnMut(&SymbolId, &mut Symbol) -> bool) {
self.symbols.retain(f);
}
pub fn nodes(&self) -> GraphElements<'_, NodeId, Node> {
GraphElements::new(&self.nodes)
}
pub fn node(&self, id: &NodeId) -> Option<&Node> {
self.nodes.get(id)
}
pub(crate) fn node_mut(&mut self, id: &NodeId) -> Option<&mut Node> {
self.nodes.get_mut(id)
}
pub(crate) fn update_node<R>(
&mut self,
id: &NodeId,
f: impl FnOnce(&mut Node) -> R,
) -> Option<R> {
self.nodes.get_mut(id).map(f)
}
pub(crate) fn insert_node(&mut self, id: NodeId, value: Node) -> Option<Node> {
self.nodes.insert(id, value)
}
pub(crate) fn remove_node(&mut self, id: &NodeId) -> Option<Node> {
self.nodes.remove(id)
}
pub(crate) fn clear_nodes(&mut self) {
self.nodes.clear();
}
pub(crate) fn retain_nodes(&mut self, f: impl FnMut(&NodeId, &mut Node) -> bool) {
self.nodes.retain(f);
}
pub fn ports(&self) -> GraphElements<'_, PortId, Port> {
GraphElements::new(&self.ports)
}
pub fn port(&self, id: &PortId) -> Option<&Port> {
self.ports.get(id)
}
pub(crate) fn port_mut(&mut self, id: &PortId) -> Option<&mut Port> {
self.ports.get_mut(id)
}
pub(crate) fn update_port<R>(
&mut self,
id: &PortId,
f: impl FnOnce(&mut Port) -> R,
) -> Option<R> {
self.ports.get_mut(id).map(f)
}
pub(crate) fn insert_port(&mut self, id: PortId, value: Port) -> Option<Port> {
self.ports.insert(id, value)
}
pub(crate) fn remove_port(&mut self, id: &PortId) -> Option<Port> {
self.ports.remove(id)
}
pub(crate) fn clear_ports(&mut self) {
self.ports.clear();
}
pub(crate) fn retain_ports(&mut self, f: impl FnMut(&PortId, &mut Port) -> bool) {
self.ports.retain(f);
}
pub fn edges(&self) -> GraphElements<'_, EdgeId, Edge> {
GraphElements::new(&self.edges)
}
pub fn edge(&self, id: &EdgeId) -> Option<&Edge> {
self.edges.get(id)
}
pub(crate) fn edge_mut(&mut self, id: &EdgeId) -> Option<&mut Edge> {
self.edges.get_mut(id)
}
pub(crate) fn update_edge<R>(
&mut self,
id: &EdgeId,
f: impl FnOnce(&mut Edge) -> R,
) -> Option<R> {
self.edges.get_mut(id).map(f)
}
pub(crate) fn insert_edge(&mut self, id: EdgeId, value: Edge) -> Option<Edge> {
self.edges.insert(id, value)
}
pub(crate) fn remove_edge(&mut self, id: &EdgeId) -> Option<Edge> {
self.edges.remove(id)
}
pub(crate) fn clear_edges(&mut self) {
self.edges.clear();
}
pub(crate) fn retain_edges(&mut self, f: impl FnMut(&EdgeId, &mut Edge) -> bool) {
self.edges.retain(f);
}
pub fn groups(&self) -> GraphElements<'_, GroupId, Group> {
GraphElements::new(&self.groups)
}
pub fn group(&self, id: &GroupId) -> Option<&Group> {
self.groups.get(id)
}
pub(crate) fn group_mut(&mut self, id: &GroupId) -> Option<&mut Group> {
self.groups.get_mut(id)
}
pub(crate) fn update_group<R>(
&mut self,
id: &GroupId,
f: impl FnOnce(&mut Group) -> R,
) -> Option<R> {
self.groups.get_mut(id).map(f)
}
pub(crate) fn insert_group(&mut self, id: GroupId, value: Group) -> Option<Group> {
self.groups.insert(id, value)
}
pub(crate) fn remove_group(&mut self, id: &GroupId) -> Option<Group> {
self.groups.remove(id)
}
pub(crate) fn clear_groups(&mut self) {
self.groups.clear();
}
pub(crate) fn retain_groups(&mut self, f: impl FnMut(&GroupId, &mut Group) -> bool) {
self.groups.retain(f);
}
pub fn sticky_notes(&self) -> GraphElements<'_, StickyNoteId, StickyNote> {
GraphElements::new(&self.sticky_notes)
}
pub fn sticky_note(&self, id: &StickyNoteId) -> Option<&StickyNote> {
self.sticky_notes.get(id)
}
pub(crate) fn sticky_note_mut(&mut self, id: &StickyNoteId) -> Option<&mut StickyNote> {
self.sticky_notes.get_mut(id)
}
pub(crate) fn update_sticky_note<R>(
&mut self,
id: &StickyNoteId,
f: impl FnOnce(&mut StickyNote) -> R,
) -> Option<R> {
self.sticky_notes.get_mut(id).map(f)
}
pub(crate) fn insert_sticky_note(
&mut self,
id: StickyNoteId,
value: StickyNote,
) -> Option<StickyNote> {
self.sticky_notes.insert(id, value)
}
pub(crate) fn remove_sticky_note(&mut self, id: &StickyNoteId) -> Option<StickyNote> {
self.sticky_notes.remove(id)
}
pub(crate) fn clear_sticky_notes(&mut self) {
self.sticky_notes.clear();
}
pub(crate) fn retain_sticky_notes(
&mut self,
f: impl FnMut(&StickyNoteId, &mut StickyNote) -> bool,
) {
self.sticky_notes.retain(f);
}
pub fn bindings(&self) -> GraphElements<'_, BindingId, Binding> {
GraphElements::new(&self.bindings)
}
pub fn binding(&self, id: &BindingId) -> Option<&Binding> {
self.bindings.get(id)
}
pub(crate) fn binding_mut(&mut self, id: &BindingId) -> Option<&mut Binding> {
self.bindings.get_mut(id)
}
pub(crate) fn update_binding<R>(
&mut self,
id: &BindingId,
f: impl FnOnce(&mut Binding) -> R,
) -> Option<R> {
self.bindings.get_mut(id).map(f)
}
pub(crate) fn insert_binding(&mut self, id: BindingId, value: Binding) -> Option<Binding> {
self.bindings.insert(id, value)
}
pub(crate) fn remove_binding(&mut self, id: &BindingId) -> Option<Binding> {
self.bindings.remove(id)
}
pub(crate) fn clear_bindings(&mut self) {
self.bindings.clear();
}
pub(crate) fn retain_bindings(&mut self, f: impl FnMut(&BindingId, &mut Binding) -> bool) {
self.bindings.retain(f);
}
}