Skip to main content

rustbac_client/
error.rs

1use rustbac_core::types::{ErrorClass, ErrorCode};
2use rustbac_datalink::DataLinkError;
3use thiserror::Error;
4
5/// Errors returned by [`BacnetClient`](crate::BacnetClient) operations.
6#[derive(Debug, Error)]
7pub enum ClientError {
8    /// The underlying transport layer returned an error (send, receive, or bind failure).
9    #[error("datalink error: {0}")]
10    DataLink(#[from] DataLinkError),
11    /// An APDU or NPDU could not be encoded into the output buffer.
12    #[error("encode error: {0}")]
13    Encode(#[from] rustbac_core::EncodeError),
14    /// An APDU or NPDU received from the network could not be decoded.
15    #[error("decode error: {0}")]
16    Decode(#[from] rustbac_core::DecodeError),
17    /// No response was received from the remote device within the configured timeout.
18    #[error("request timed out")]
19    Timeout,
20    /// The remote device responded with a BACnet Error PDU for `service_choice`.
21    ///
22    /// The raw numeric error class and code are always present when the device sends them;
23    /// the typed variants are `Some` only when the values are recognised by this library.
24    #[error("remote service error for service choice {service_choice}")]
25    RemoteServiceError {
26        service_choice: u8,
27        error_class_raw: Option<u32>,
28        error_code_raw: Option<u32>,
29        error_class: Option<ErrorClass>,
30        error_code: Option<ErrorCode>,
31    },
32    /// The remote device rejected the request with the given BACnet reject reason code.
33    #[error("remote reject reason {reason}")]
34    RemoteReject { reason: u8 },
35    /// The remote device (or router) aborted the transaction. `server` is `true` when
36    /// the Abort PDU was sent by the server side.
37    #[error("remote abort reason {reason} (server={server})")]
38    RemoteAbort { reason: u8, server: bool },
39    /// A segment-ACK with the negative-ACK bit set was received for `sequence_number`
40    /// during a segmented confirmed request.
41    #[error("segment ack negative for sequence {sequence_number}")]
42    SegmentNegativeAck { sequence_number: u8 },
43    /// The encoded request payload is too large to fit within 255 segments of the
44    /// negotiated maximum APDU size.
45    #[error("segmented request too large")]
46    SegmentedRequestTooLarge,
47    /// The reassembled segmented response exceeded the internal 1 MiB safety limit.
48    #[error("response payload exceeded {limit} bytes")]
49    ResponseTooLarge { limit: usize },
50    /// The response received from the device was syntactically valid but not understood
51    /// (e.g. unexpected APDU type, missing required fields, or unsupported segmentation).
52    #[error("unsupported response")]
53    UnsupportedResponse,
54    /// A `CovManager` or other component attempted to spawn a Tokio task outside of a
55    /// Tokio runtime context.
56    #[error("no active Tokio runtime — build() must be called from within a tokio::Runtime")]
57    NoTokioRuntime,
58}