use crate::attributes::compass_point::CompassPoint; use crate::dot::DotString; use std::borrow::Cow; /// Modifier indicating where on a node an edge should be aimed. /// If Port is used, the corresponding node must either have record shape with one of its /// fields having the given portname, or have an HTML-like label, one of whose components has a /// PORT attribute set to portname. /// If no compass point is used with a portname, the default value is "_". #[derive(Clone, PartialEq, Eq, Debug)] pub enum PortPosition { Port { port_name: String, compass_point: Option, }, Compass(CompassPoint), } impl<'a> DotString<'a> for PortPosition { fn dot_string(&self) -> Cow<'a, str> { match self { PortPosition::Port { port_name, compass_point, } => { let mut dot_string = port_name.to_owned(); if let Some(compass_point) = compass_point { dot_string .push_str(format!(":{}", compass_point.dot_string()).as_str()); } dot_string.into() } PortPosition::Compass(p) => p.dot_string().into(), } } } #[cfg(test)] mod test { use crate::attributes::{CompassPoint, PortPosition}; use crate::DotString; #[test] fn port_dot_string() { assert_eq!( "port_0", PortPosition::Port { port_name: "port_0".to_string(), compass_point: None } .dot_string() ); assert_eq!( "port_0:ne", PortPosition::Port { port_name: "port_0".to_string(), compass_point: Some(CompassPoint::NE) } .dot_string() ); } #[test] fn compass_dot_string() { assert_eq!("ne", PortPosition::Compass(CompassPoint::NE).dot_string()); } }