Skip to main content

bacnet_objects/
present_value_access.rs

1//! How a Value object's Present_Value is written.
2
3use std::borrow::Cow;
4
5use bacnet_types::enums::PropertyIdentifier;
6
7use crate::property_metadata::{
8    PropertyMetadata, PropertyPresenceCondition, PropertyWriteCapability,
9};
10
11/// How peers and the local application write a Value object's Present_Value.
12///
13/// Priority_Array, Relinquish_Default, Current_Command_Priority and the
14/// command-source properties are present only under [`Commandable`](Self::Commandable).
15/// Under every access, Out_Of_Service TRUE keeps the local application from
16/// changing Present_Value and lets peers write it for testing (Clause 12,
17/// Out_Of_Service of each Value object).
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
19pub enum PresentValueAccess {
20    /// The application sets Present_Value. Peers write it only while
21    /// Out_Of_Service is TRUE.
22    ReadOnly,
23    /// A peer write replaces Present_Value, and so does the application.
24    Writable,
25    /// Peer writes go through Priority_Array, and the highest occupied
26    /// priority is Present_Value (Clause 19.2).
27    #[default]
28    Commandable,
29}
30
31impl PresentValueAccess {
32    /// Whether a row with this presence condition exists under this access.
33    pub(crate) fn includes(self, condition: Option<PropertyPresenceCondition>) -> bool {
34        self == Self::Commandable
35            || !matches!(
36                condition,
37                Some(
38                    PropertyPresenceCondition::Commandable
39                        | PropertyPresenceCondition::CommandableAuditReporting
40                        | PropertyPresenceCondition::ValueSourceTracking
41                        | PropertyPresenceCondition::CommandableValueSourceTracking
42                )
43            )
44    }
45
46    /// `rows` as this access presents them: the rows it excludes removed, and
47    /// Present_Value's write capability set to match.
48    pub(crate) fn project(self, rows: Cow<'_, [PropertyMetadata]>) -> Cow<'_, [PropertyMetadata]> {
49        let present_value = match self {
50            Self::Commandable => return rows,
51            Self::Writable => PropertyWriteCapability::Always,
52            Self::ReadOnly => PropertyWriteCapability::WhenOutOfService,
53        };
54
55        Cow::Owned(
56            rows.iter()
57                .filter(|row| self.includes(row.presence_condition))
58                .map(|row| {
59                    if row.property_identifier == PropertyIdentifier::PRESENT_VALUE {
60                        PropertyMetadata::new(
61                            row.property_identifier,
62                            row.conformance,
63                            row.presence_condition,
64                            present_value,
65                        )
66                    } else {
67                        *row
68                    }
69                })
70                .collect(),
71        )
72    }
73
74    /// Whether `rows` hold `property` under a condition this access excludes.
75    pub(crate) fn excludes(self, rows: &[PropertyMetadata], property: PropertyIdentifier) -> bool {
76        self != Self::Commandable
77            && rows.iter().any(|row| {
78                row.property_identifier == property && !self.includes(row.presence_condition)
79            })
80    }
81}