blob: 5874b8fb97596b687f0c380ba055afff4af1ff74 [file] [log] [blame]
use alloc::vec::Vec;
use core::{
cmp::Ordering,
fmt::{Debug, Display, Formatter},
hash::{Hash, Hasher},
iter::once,
};
use petgraph_core::{GraphStorage, Node};
pub struct Path<'graph, S>
where
S: GraphStorage,
{
source: Node<'graph, S>,
target: Node<'graph, S>,
transit: Vec<Node<'graph, S>>,
}
impl<'graph, S> Path<'graph, S>
where
S: GraphStorage,
{
#[must_use]
pub fn new(
source: Node<'graph, S>,
transit: Vec<Node<'graph, S>>,
target: Node<'graph, S>,
) -> Self {
Self {
source,
target,
transit,
}
}
#[must_use]
pub const fn source(&self) -> Node<'graph, S> {
self.source
}
#[must_use]
pub const fn target(&self) -> Node<'graph, S> {
self.target
}
#[must_use]
pub fn transit(&self) -> &[Node<'graph, S>] {
&self.transit
}
#[must_use]
pub fn to_vec(self) -> Vec<Node<'graph, S>> {
let mut vec = Vec::with_capacity(self.transit.len() + 2);
vec.push(self.source);
vec.extend(self.transit);
vec.push(self.target);
vec
}
pub fn iter(&self) -> impl Iterator<Item = Node<'graph, S>> + '_ {
once(self.source)
.chain(self.transit.iter().copied())
.chain(once(self.target))
}
pub(in crate::shortest_paths) fn reverse(self) -> Self {
let mut transit = self.transit;
transit.reverse();
Self {
source: self.target,
target: self.source,
transit,
}
}
}
// ensure that all traits have been implemented
// see: https://rust-lang.github.io/api-guidelines/interoperability.html
#[cfg(test)]
static_assertions::assert_impl_all!(Path<'_, petgraph_dino::DinoStorage<(), ()>>: Debug, Display, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Send, Sync);
impl<'graph, S> Debug for Path<'graph, S>
where
S: GraphStorage,
Node<'graph, S>: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Path")
.field("source", &self.source)
.field("target", &self.target)
.field("transit", &self.transit)
.finish()
}
}
impl<S> Display for Path<'_, S>
where
S: GraphStorage,
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
Display::fmt(&self.source.id(), f)?;
for node in &self.transit {
write!(f, " -> {}", node.id())?;
}
write!(f, " -> {}", self.target.id())
}
}
impl<S> Clone for Path<'_, S>
where
S: GraphStorage,
{
fn clone(&self) -> Self {
Self {
source: self.source,
target: self.target,
transit: self.transit.clone(),
}
}
}
impl<'graph, S> PartialEq for Path<'graph, S>
where
S: GraphStorage,
Node<'graph, S>: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
(&self.source, &self.target, &self.transit)
== (&other.source, &other.target, &other.transit)
}
}
impl<'graph, S> Eq for Path<'graph, S>
where
S: GraphStorage,
Node<'graph, S>: Eq,
{
}
impl<'graph, S> PartialOrd for Path<'graph, S>
where
S: GraphStorage,
Node<'graph, S>: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
(&self.source, &self.transit, &self.target).partial_cmp(&(
&other.source,
&other.transit,
&other.target,
))
}
}
impl<'graph, S> Ord for Path<'graph, S>
where
S: GraphStorage,
Node<'graph, S>: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
(&self.source, &self.transit, &self.target).cmp(&(
&other.source,
&other.transit,
&other.target,
))
}
}
impl<'graph, S> Hash for Path<'graph, S>
where
S: GraphStorage,
Node<'graph, S>: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
(&self.source, &self.target, &self.transit).hash(state);
}
}
impl<'graph, S> IntoIterator for Path<'graph, S>
where
S: GraphStorage,
{
type IntoIter = alloc::vec::IntoIter<Node<'graph, S>>;
type Item = Node<'graph, S>;
fn into_iter(self) -> Self::IntoIter {
self.to_vec().into_iter()
}
}