bacnet_encoding/apdu/remote_error.rs
1//! How a refusal PDU reads as a [`RemoteError`] (#2026).
2//!
3//! The client's dispatch, its endpoint requester and the server's
4//! notification transactions all turn an Error, Reject or Abort PDU into the
5//! same [`RemoteError`]; these helpers are the one place that mapping lives.
6
7use bacnet_types::error::RemoteError;
8
9use super::{AbortPdu, Apdu, ErrorPdu, RejectPdu};
10
11impl ErrorPdu {
12 /// The refusal as a [`RemoteError::Error`]: the class and code.
13 ///
14 /// Any service-specific body after the class and code (`error_data`) is
15 /// not part of it; a caller that reports a structured error reads that
16 /// body itself.
17 #[must_use]
18 pub const fn remote_error(&self) -> RemoteError {
19 RemoteError::Error {
20 class: self.error_class,
21 code: self.error_code,
22 }
23 }
24}
25
26impl RejectPdu {
27 /// The refusal as a [`RemoteError::Reject`] carrying the reason.
28 #[must_use]
29 pub const fn remote_error(&self) -> RemoteError {
30 RemoteError::Reject {
31 reason: self.reject_reason,
32 }
33 }
34}
35
36impl AbortPdu {
37 /// The refusal as a [`RemoteError::Abort`] carrying the reason.
38 ///
39 /// It doesn't look at `sent_by_server`: whether an Abort may end a
40 /// transaction is the caller's decision.
41 #[must_use]
42 pub const fn remote_error(&self) -> RemoteError {
43 RemoteError::Abort {
44 reason: self.abort_reason,
45 }
46 }
47}
48
49impl Apdu {
50 /// How the peer turned the request down, for an Error, Reject or Abort
51 /// PDU; `None` for every other PDU type.
52 ///
53 /// A convenience for code holding an `Apdu` of unknown type; the stack's
54 /// own dispatch has already matched the PDU type and calls the
55 /// per-PDU `remote_error()` instead.
56 #[must_use]
57 pub const fn remote_error(&self) -> Option<RemoteError> {
58 match self {
59 Self::Error(pdu) => Some(pdu.remote_error()),
60 Self::Reject(pdu) => Some(pdu.remote_error()),
61 Self::Abort(pdu) => Some(pdu.remote_error()),
62 Self::ConfirmedRequest(_)
63 | Self::UnconfirmedRequest(_)
64 | Self::SimpleAck(_)
65 | Self::ComplexAck(_)
66 | Self::SegmentAck(_) => None,
67 }
68 }
69}