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}