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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! Audit notification and query wire models.
//!
//! These codecs follow the corrected 2020 baseline: ANSI/ASHRAE 135-2020 plus
//! the Errata Summary 2024-04-29 (v1), visually verified from the rendered
//! errata page 3 under its page-1 convention (strikeout = removed, italics =
//! added) and recorded by RB-01. Item 7 (Clause 21.6, printed p. 886)
//! corrects the by-target/by-source `successful-actions-only` fields from
//! BOOLEAN to `BACnetSuccessFilter` at unchanged tags \[7\]/\[4\]; item 8
//! (Clause 21.2.3, printed p. 865) corrects `start-at-sequence-number` from
//! Unsigned32 to Unsigned64 at unchanged optional tag \[2\]. Unsigned values
//! use the library's `u64` implementation limit (1-8 octet canonical forms).
pub use bacnet_types::constructed::{
AuditPropertyReference, BACnetAuditLogDatum, BACnetAuditLogQueryParameters,
BACnetAuditLogRecord, BACnetAuditLogRecordResult, BACnetAuditNotification,
};
use bacnet_types::error::Error;
use bacnet_types::primitives::ObjectIdentifier;
use bytes::BytesMut;
#[path = "audit/notification_codec.rs"]
mod notification_codec;
#[path = "audit/query_ack_codec.rs"]
mod query_ack_codec;
#[path = "audit/query_codec.rs"]
mod query_codec;
/// Parameters shared by confirmed and unconfirmed AuditNotification.
#[derive(Debug, Clone, PartialEq)]
pub struct AuditNotificationRequest {
/// One or more notifications, encoded under context tag `[0]`.
pub notifications: Vec<BACnetAuditNotification>,
}
/// AuditLogQuery-ACK service parameters.
///
/// This wire model does not perform storage queries or infer record ordering,
/// continuity, filtering, or the truth of `no_more_items`.
#[derive(Debug, Clone, PartialEq)]
pub struct AuditLogQueryAck {
/// Audit Log object whose records were queried.
pub audit_log: ObjectIdentifier,
/// Zero or more adjacent record results encoded under context tag `[1]`.
pub records: Vec<BACnetAuditLogRecordResult>,
/// `true` when no records remain beyond those returned; the codec does not verify it.
pub no_more_items: bool,
}
/// AuditLogQuery-Request service parameters.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AuditLogQueryRequest {
/// Audit Log object to query.
pub audit_log: ObjectIdentifier,
/// Filter selecting which records to return.
pub query_parameters: BACnetAuditLogQueryParameters,
/// Corrected-baseline `Unsigned64` cursor (Errata 2024-04-29 item 8).
pub start_at_sequence_number: Option<u64>,
/// Maximum number of records the requester wants returned.
pub requested_count: u16,
}
impl AuditNotificationRequest {
/// Encode after validation, leaving `buf` unchanged on failure.
pub fn try_encode(&self, buf: &mut BytesMut) -> Result<(), Error> {
notification_codec::encode(self, buf)
}
/// Encode the request into `buf`; same as `try_encode`.
pub fn encode(&self, buf: &mut BytesMut) -> Result<(), Error> {
self.try_encode(buf)
}
/// Decode a complete payload; trailing bytes are rejected.
pub fn decode(data: &[u8]) -> Result<Self, Error> {
notification_codec::decode(data)
}
}
impl AuditLogQueryRequest {
/// Encode after validation, leaving `buf` unchanged on failure.
pub fn try_encode(&self, buf: &mut BytesMut) -> Result<(), Error> {
query_codec::encode(self, buf)
}
/// Encode the request into `buf`; same as `try_encode`.
pub fn encode(&self, buf: &mut BytesMut) -> Result<(), Error> {
self.try_encode(buf)
}
/// Decode a complete payload; trailing bytes are rejected.
pub fn decode(data: &[u8]) -> Result<Self, Error> {
query_codec::decode(data)
}
}
impl AuditLogQueryAck {
/// Encode after validation, leaving `buf` unchanged on failure.
pub fn try_encode(&self, buf: &mut BytesMut) -> Result<(), Error> {
query_ack_codec::encode(self, buf)
}
/// Encode the ACK into `buf`; same as `try_encode`.
pub fn encode(&self, buf: &mut BytesMut) -> Result<(), Error> {
self.try_encode(buf)
}
/// Decode a complete payload; trailing bytes are rejected.
pub fn decode(data: &[u8]) -> Result<Self, Error> {
query_ack_codec::decode(data)
}
}
#[cfg(test)]
#[path = "audit/tests.rs"]
mod tests;
#[cfg(test)]
#[path = "audit/malformed_tests.rs"]
mod malformed_tests;
#[cfg(test)]
#[path = "audit/empty_value_tests.rs"]
mod empty_value_tests;
#[cfg(test)]
#[path = "audit/address_bound_tests.rs"]
mod address_bound_tests;