Skip to main content

ifc_systems/flow/
direction.rs

1//! `IfcFlowDirectionEnum` and what it licenses.
2//!
3//! The enum is a port attribute, but its MEANING is a flow concern: it decides
4//! which way an edge may be walked. Keeping the semantics here rather than on
5//! the port keeps "what the file says" separate from "what that implies".
6
7use ifc_model::Value;
8
9/// Which way material or energy moves through a port.
10///
11/// A missing direction is [`FlowDirection::NotDefined`] rather than an assumed
12/// default. Guessing `Source` would invent a direction the file never stated
13/// and orient edges that have no stated orientation, which is worse than
14/// admitting the network is partly undirected.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
16pub enum FlowDirection {
17    /// Material leaves the element through this port.
18    Source,
19    /// Material enters the element through this port.
20    Sink,
21    /// Bidirectional.
22    SourceAndSink,
23    /// Stated as NOTDEFINED, or not stated at all.
24    NotDefined,
25}
26
27impl FlowDirection {
28    /// Read the enum from an attribute slot.
29    pub(crate) fn parse(value: Option<&Value>) -> Self {
30        match value {
31            Some(Value::Enum(name)) => match name.to_ascii_uppercase().as_str() {
32                "SOURCE" => Self::Source,
33                "SINK" => Self::Sink,
34                "SOURCEANDSINK" => Self::SourceAndSink,
35                _ => Self::NotDefined,
36            },
37            _ => Self::NotDefined,
38        }
39    }
40
41    /// Whether material may LEAVE the element through this port.
42    ///
43    /// `NotDefined` is false in both directions. That is deliberate: an
44    /// undirected port cannot orient an edge, and pretending it can would
45    /// manufacture flow paths a reviewer cannot trace back to the file.
46    pub fn emits(self) -> bool {
47        matches!(self, Self::Source | Self::SourceAndSink)
48    }
49
50    /// Whether material may ENTER the element through this port.
51    pub fn accepts(self) -> bool {
52        matches!(self, Self::Sink | Self::SourceAndSink)
53    }
54
55    /// Whether the file stated a direction at all.
56    pub fn is_stated(self) -> bool {
57        !matches!(self, Self::NotDefined)
58    }
59}