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}