summaryrefslogtreecommitdiff
path: root/src/attributes/port_position.rs
blob: a492b141a1cbba83ad0a47423d5c2cb2605f3f6c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum PortPosition {
    Port {
        port_name: String,
        compass_point: Option<CompassPoint>,
    },
    Compass(CompassPoint),
}

// TODO: AsRef vs this?
// See https://github.com/Peternator7/strum/blob/96ee0a9a307ec7d1a39809fb59037bd4e11557cc/strum/src/lib.rs
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::{PortPosition, CompassPoint};
    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());
    }
}