use std::collections::{BTreeSet, HashSet};
use std::fmt::{Debug, Display};
use std::hash::Hash;
pub trait Endpoints: Clone + IntoIterator<Item = Self::NodeIx> + Eq + Debug {
type NodeIx: Copy + Eq + Ord + Hash + Display + Debug;
fn iter(&self) -> Self::IntoIter {
self.clone().into_iter()
}
fn try_from_node_indices(nodes: impl IntoIterator<Item = Self::NodeIx>) -> Option<Self>;
fn try_from_sources_targets(
source: impl IntoIterator<Item = Self::NodeIx>,
target: impl IntoIterator<Item = Self::NodeIx>,
) -> Option<Self>;
}
pub trait Map<BaseNodeIx>: Endpoints {
type Mapped: Endpoints<NodeIx = BaseNodeIx>;
fn map_forward(self, f: impl FnMut(Self::NodeIx) -> BaseNodeIx) -> Self::Mapped;
fn map_backward(mapped: Self::Mapped, f: impl FnMut(BaseNodeIx) -> Self::NodeIx) -> Self;
}
impl<Nx: Copy + Eq + Ord + Hash + Display + Debug> Endpoints for [Nx; 2] {
type NodeIx = Nx;
fn try_from_node_indices(nodes: impl IntoIterator<Item = Self::NodeIx>) -> Option<Self> {
let mut iter = nodes.into_iter();
let a = iter.next()?;
let b = iter.next()?;
if iter.next().is_some() {
return None;
}
Some([a, b])
}
fn try_from_sources_targets(
source: impl IntoIterator<Item = Self::NodeIx>,
target: impl IntoIterator<Item = Self::NodeIx>,
) -> Option<Self> {
let mut s = source.into_iter();
let mut t = target.into_iter();
let src = s.next()?;
let dst = t.next()?;
if s.next().is_some() || t.next().is_some() {
return None;
}
Some([src, dst])
}
}
impl<Nx, NewNx> Map<NewNx> for [Nx; 2]
where
Nx: Copy + Eq + Ord + Hash + Display + Debug,
NewNx: Copy + Eq + Ord + Hash + Display + Debug,
{
type Mapped = [NewNx; 2];
fn map_forward(self, mut f: impl FnMut(Nx) -> NewNx) -> [NewNx; 2] {
[f(self[0]), f(self[1])]
}
fn map_backward(mapped: Self::Mapped, mut f: impl FnMut(NewNx) -> Self::NodeIx) -> Self {
[f(mapped[0]), f(mapped[1])]
}
}
impl<Nx: Copy + Eq + Ord + Hash + Display + Debug> Endpoints for HashSet<Nx> {
type NodeIx = Nx;
fn try_from_node_indices(nodes: impl IntoIterator<Item = Self::NodeIx>) -> Option<Self> {
Some(nodes.into_iter().collect())
}
fn try_from_sources_targets(
source: impl IntoIterator<Item = Self::NodeIx>,
target: impl IntoIterator<Item = Self::NodeIx>,
) -> Option<Self> {
Some(source.into_iter().chain(target).collect())
}
}
impl<Nx, NewNx> Map<NewNx> for HashSet<Nx>
where
Nx: Copy + Eq + Ord + Hash + Display + Debug,
NewNx: Copy + Eq + Ord + Hash + Display + Debug,
{
type Mapped = HashSet<NewNx>;
fn map_forward(self, f: impl FnMut(Nx) -> NewNx) -> HashSet<NewNx> {
self.into_iter().map(f).collect()
}
fn map_backward(mapped: Self::Mapped, f: impl FnMut(NewNx) -> Self::NodeIx) -> Self {
mapped.into_iter().map(f).collect()
}
}
impl<Nx: Copy + Eq + Ord + Hash + Display + Debug> Endpoints for BTreeSet<Nx> {
type NodeIx = Nx;
fn try_from_node_indices(nodes: impl IntoIterator<Item = Self::NodeIx>) -> Option<Self> {
Some(nodes.into_iter().collect())
}
fn try_from_sources_targets(
source: impl IntoIterator<Item = Self::NodeIx>,
target: impl IntoIterator<Item = Self::NodeIx>,
) -> Option<Self> {
Some(source.into_iter().chain(target).collect())
}
}
impl<Nx, NewNx> Map<NewNx> for BTreeSet<Nx>
where
Nx: Copy + Eq + Ord + Hash + Display + Debug,
NewNx: Copy + Eq + Ord + Hash + Display + Debug,
{
type Mapped = BTreeSet<NewNx>;
fn map_forward(self, f: impl FnMut(Nx) -> NewNx) -> BTreeSet<NewNx> {
self.into_iter().map(f).collect()
}
fn map_backward(mapped: Self::Mapped, f: impl FnMut(NewNx) -> Self::NodeIx) -> Self {
mapped.into_iter().map(f).collect()
}
}
impl<Nx: Copy + Eq + Ord + Hash + Display + Debug> Endpoints for Vec<Nx> {
type NodeIx = Nx;
fn try_from_node_indices(nodes: impl IntoIterator<Item = Nx>) -> Option<Self> {
Some(nodes.into_iter().collect())
}
fn try_from_sources_targets(
source: impl IntoIterator<Item = Nx>,
target: impl IntoIterator<Item = Nx>,
) -> Option<Self> {
Some(source.into_iter().chain(target).collect())
}
}