hugr_core/hugr/
internal.rsuse std::borrow::Cow;
use std::ops::Range;
use std::rc::Rc;
use std::sync::Arc;
use delegate::delegate;
use portgraph::{LinkView, MultiPortGraph, PortMut, PortView};
use crate::ops::handle::NodeHandle;
use crate::ops::OpTrait;
use crate::{Direction, Hugr, Node};
use super::hugrmut::{panic_invalid_node, panic_invalid_non_root};
use super::{HugrError, OpType, RootTagged};
pub trait HugrInternals {
type Portgraph<'p>: LinkView + Clone + 'p
where
Self: 'p;
fn portgraph(&self) -> Self::Portgraph<'_>;
fn base_hugr(&self) -> &Hugr;
fn root_node(&self) -> Node;
}
impl HugrInternals for Hugr {
type Portgraph<'p>
= &'p MultiPortGraph
where
Self: 'p;
#[inline]
fn portgraph(&self) -> Self::Portgraph<'_> {
&self.graph
}
#[inline]
fn base_hugr(&self) -> &Hugr {
self
}
#[inline]
fn root_node(&self) -> Node {
self.root.into()
}
}
impl<T: HugrInternals> HugrInternals for &T {
type Portgraph<'p>
= T::Portgraph<'p>
where
Self: 'p;
delegate! {
to (**self) {
fn portgraph(&self) -> Self::Portgraph<'_>;
fn base_hugr(&self) -> &Hugr;
fn root_node(&self) -> Node;
}
}
}
impl<T: HugrInternals> HugrInternals for &mut T {
type Portgraph<'p>
= T::Portgraph<'p>
where
Self: 'p;
delegate! {
to (**self) {
fn portgraph(&self) -> Self::Portgraph<'_>;
fn base_hugr(&self) -> &Hugr;
fn root_node(&self) -> Node;
}
}
}
impl<T: HugrInternals> HugrInternals for Rc<T> {
type Portgraph<'p>
= T::Portgraph<'p>
where
Self: 'p;
delegate! {
to (**self) {
fn portgraph(&self) -> Self::Portgraph<'_>;
fn base_hugr(&self) -> &Hugr;
fn root_node(&self) -> Node;
}
}
}
impl<T: HugrInternals> HugrInternals for Arc<T> {
type Portgraph<'p>
= T::Portgraph<'p>
where
Self: 'p;
delegate! {
to (**self) {
fn portgraph(&self) -> Self::Portgraph<'_>;
fn base_hugr(&self) -> &Hugr;
fn root_node(&self) -> Node;
}
}
}
impl<T: HugrInternals> HugrInternals for Box<T> {
type Portgraph<'p>
= T::Portgraph<'p>
where
Self: 'p;
delegate! {
to (**self) {
fn portgraph(&self) -> Self::Portgraph<'_>;
fn base_hugr(&self) -> &Hugr;
fn root_node(&self) -> Node;
}
}
}
impl<T: HugrInternals + ToOwned> HugrInternals for Cow<'_, T> {
type Portgraph<'p>
= T::Portgraph<'p>
where
Self: 'p;
delegate! {
to self.as_ref() {
fn portgraph(&self) -> Self::Portgraph<'_>;
fn base_hugr(&self) -> &Hugr;
fn root_node(&self) -> Node;
}
}
}
pub trait HugrMutInternals: RootTagged {
fn hugr_mut(&mut self) -> &mut Hugr;
fn set_num_ports(&mut self, node: Node, incoming: usize, outgoing: usize) {
panic_invalid_node(self, node);
self.hugr_mut().set_num_ports(node, incoming, outgoing)
}
fn add_ports(&mut self, node: Node, direction: Direction, amount: isize) -> Range<usize> {
panic_invalid_node(self, node);
self.hugr_mut().add_ports(node, direction, amount)
}
fn set_parent(&mut self, node: Node, parent: Node) {
panic_invalid_node(self, parent);
panic_invalid_non_root(self, node);
self.hugr_mut().set_parent(node, parent);
}
fn move_after_sibling(&mut self, node: Node, after: Node) {
panic_invalid_non_root(self, node);
panic_invalid_non_root(self, after);
self.hugr_mut().move_after_sibling(node, after);
}
fn move_before_sibling(&mut self, node: Node, before: Node) {
panic_invalid_non_root(self, node);
panic_invalid_non_root(self, before);
self.hugr_mut().move_before_sibling(node, before)
}
fn replace_op(&mut self, node: Node, op: impl Into<OpType>) -> Result<OpType, HugrError> {
panic_invalid_node(self, node);
let op = op.into();
if node == self.root() && !Self::RootHandle::TAG.is_superset(op.tag()) {
return Err(HugrError::InvalidTag {
required: Self::RootHandle::TAG,
actual: op.tag(),
});
}
self.hugr_mut().replace_op(node, op)
}
}
impl<T: RootTagged<RootHandle = Node> + AsMut<Hugr>> HugrMutInternals for T {
fn hugr_mut(&mut self) -> &mut Hugr {
self.as_mut()
}
#[inline]
fn set_num_ports(&mut self, node: Node, incoming: usize, outgoing: usize) {
self.hugr_mut()
.graph
.set_num_ports(node.pg_index(), incoming, outgoing, |_, _| {})
}
fn add_ports(&mut self, node: Node, direction: Direction, amount: isize) -> Range<usize> {
let mut incoming = self.hugr_mut().graph.num_inputs(node.pg_index());
let mut outgoing = self.hugr_mut().graph.num_outputs(node.pg_index());
let increment = |num: &mut usize| {
let new = num.saturating_add_signed(amount);
let range = *num..new;
*num = new;
range
};
let range = match direction {
Direction::Incoming => increment(&mut incoming),
Direction::Outgoing => increment(&mut outgoing),
};
self.hugr_mut()
.graph
.set_num_ports(node.pg_index(), incoming, outgoing, |_, _| {});
range
}
fn set_parent(&mut self, node: Node, parent: Node) {
self.hugr_mut().hierarchy.detach(node.pg_index());
self.hugr_mut()
.hierarchy
.push_child(node.pg_index(), parent.pg_index())
.expect("Inserting a newly-created node into the hierarchy should never fail.");
}
fn move_after_sibling(&mut self, node: Node, after: Node) {
self.hugr_mut().hierarchy.detach(node.pg_index());
self.hugr_mut()
.hierarchy
.insert_after(node.pg_index(), after.pg_index())
.expect("Inserting a newly-created node into the hierarchy should never fail.");
}
fn move_before_sibling(&mut self, node: Node, before: Node) {
self.hugr_mut().hierarchy.detach(node.pg_index());
self.hugr_mut()
.hierarchy
.insert_before(node.pg_index(), before.pg_index())
.expect("Inserting a newly-created node into the hierarchy should never fail.");
}
fn replace_op(&mut self, node: Node, op: impl Into<OpType>) -> Result<OpType, HugrError> {
let cur = self.hugr_mut().op_types.get_mut(node.pg_index());
Ok(std::mem::replace(cur, op.into()))
}
}