Skip to main content

sparkplug_b/
error.rs

1//! The crate-wide error type and result alias.
2//!
3//! A single [`SparkplugError`] models every fallible operation (parsing,
4//! encoding, decoding, persistence). Per the Rust API guidelines we never
5//! `panic!` on untrusted input — every decode failure is a typed variant.
6
7/// Convenient result alias used throughout the crate.
8pub type Result<T> = std::result::Result<T, SparkplugError>;
9
10/// Errors produced while building, encoding, decoding, or parsing Sparkplug B data.
11#[derive(Debug, thiserror::Error)]
12#[non_exhaustive]
13pub enum SparkplugError {
14    /// A topic string was not a valid Sparkplug B topic.
15    #[error("invalid Sparkplug topic: {0}")]
16    InvalidTopic(String),
17
18    /// A Group/Edge-Node/Device identifier was empty or contained a reserved
19    /// character (`+`, `/`, `#`).
20    #[error("invalid Sparkplug identifier: {0}")]
21    InvalidId(String),
22
23    /// The protobuf byte stream ended unexpectedly.
24    #[error("unexpected end of input while decoding protobuf")]
25    Truncated,
26
27    /// A protobuf varint exceeded 64 bits.
28    #[error("protobuf varint overflowed 64 bits")]
29    VarintOverflow,
30
31    /// A protobuf field used a wire type the schema does not allow.
32    #[error("unsupported protobuf wire type {0}")]
33    InvalidWireType(u8),
34
35    /// A string field was not valid UTF-8.
36    #[error("invalid UTF-8 in string field")]
37    InvalidUtf8,
38
39    /// A datatype code on the wire was not one of the enumerated Sparkplug data types.
40    #[error("unknown Sparkplug data type code {0}")]
41    UnknownDataType(u32),
42
43    /// A DATA/CMD metric omitted its datatype and it could not be recovered
44    /// from a prior birth (by name or alias).
45    #[error("missing datatype for metric (no birth/alias mapping): {0}")]
46    MissingDataType(String),
47
48    /// A packed numeric array had a length that is not a multiple of the element width.
49    #[error("packed array length {len} is not a multiple of element width {width}")]
50    ArrayLength {
51        /// The byte length found on the wire.
52        len: usize,
53        /// The expected per-element width in bytes.
54        width: usize,
55    },
56
57    /// A DataSet's `columns`/`types`/`rows` shapes were inconsistent.
58    #[error("invalid DataSet shape: {0}")]
59    DataSetShape(String),
60
61    /// A metric's value did not match the field set expected for its datatype.
62    #[error("value/datatype mismatch: {0}")]
63    ValueTypeMismatch(String),
64
65    /// Decoding hit the maximum nesting depth (defends against hostile inputs).
66    #[error("maximum nesting depth exceeded while decoding")]
67    RecursionLimit,
68
69    /// A STATE JSON payload was malformed.
70    #[error("invalid STATE payload: {0}")]
71    InvalidState(String),
72
73    /// An I/O error from bdSeq persistence.
74    #[error("bdSeq store I/O error: {0}")]
75    Io(#[from] std::io::Error),
76
77    /// An MQTT transport error (connect/subscribe/publish/receive).
78    #[error("MQTT transport error: {0}")]
79    Transport(String),
80}