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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! How a Value object's Present_Value is written.
use std::borrow::Cow;
use bacnet_types::enums::PropertyIdentifier;
use crate::property_metadata::{
PropertyMetadata, PropertyPresenceCondition, PropertyWriteCapability,
};
/// How peers and the local application write a Value object's Present_Value.
///
/// Priority_Array, Relinquish_Default, Current_Command_Priority,
/// Value_Source_Array and Last_Command_Time are present only under
/// [`Commandable`](Self::Commandable). Value_Source is too, unless the object
/// tracks the source of its noncommandable Present_Value (`set_value_source_tracking`
/// on each Value object, #1552).
/// Under every access, Out_Of_Service TRUE keeps the local application from
/// changing Present_Value and lets peers write it for testing (Clause 12,
/// Out_Of_Service of each Value object).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum PresentValueAccess {
/// The application sets Present_Value. Peers write it only while
/// Out_Of_Service is TRUE.
ReadOnly,
/// A peer write replaces Present_Value, and so does the application.
Writable,
/// Peer writes go through Priority_Array, and the highest occupied
/// priority is Present_Value (Clause 19.2).
#[default]
Commandable,
}
impl PresentValueAccess {
/// Whether a row with this presence condition exists under this access.
/// `source_tracked` says whether a noncommandable object tracks its
/// Present_Value's source, which keeps its Value_Source row.
pub(crate) fn includes(
self,
condition: Option<PropertyPresenceCondition>,
source_tracked: bool,
) -> bool {
use PropertyPresenceCondition as C;
self == Self::Commandable
|| match condition {
Some(
C::Commandable
| C::CommandableAuditReporting
| C::CommandableValueSourceTracking,
) => false,
Some(C::ValueSourceTracking) => source_tracked,
_ => true,
}
}
/// `rows` as this access presents them: the rows it excludes removed, and
/// Present_Value's write capability set to match.
pub(crate) fn project(
self,
rows: Cow<'_, [PropertyMetadata]>,
source_tracked: bool,
) -> Cow<'_, [PropertyMetadata]> {
let present_value = match self {
Self::Commandable => return rows,
Self::Writable => PropertyWriteCapability::Always,
Self::ReadOnly => PropertyWriteCapability::WhenOutOfService,
};
Cow::Owned(
rows.iter()
.filter(|row| self.includes(row.presence_condition, source_tracked))
.map(|row| {
if row.property_identifier == PropertyIdentifier::PRESENT_VALUE {
PropertyMetadata::new(
row.property_identifier,
row.conformance,
row.presence_condition,
present_value,
)
} else {
*row
}
})
.collect(),
)
}
/// Whether `rows` hold `property` under a condition this access excludes.
pub(crate) fn excludes(
self,
rows: &[PropertyMetadata],
property: PropertyIdentifier,
source_tracked: bool,
) -> bool {
self != Self::Commandable
&& rows.iter().any(|row| {
row.property_identifier == property
&& !self.includes(row.presence_condition, source_tracked)
})
}
}