Skip to main content

moddef_core/
error.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Typed errors (spec §26.3/§26.4, §32). Structured variants rather than
4//! strings; `Display` always, `std::error::Error` under `std`.
5
6use core::fmt;
7
8/// Codec decode failure causes.
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub enum DecodeError {
11    /// scale_ref / selector_ref target not resolved in the context.
12    UnresolvedRef,
13    ZeroScaleDenominator,
14    ComposedBaseZero,
15    /// Register slice shorter than the point's width.
16    ShortRead,
17    /// Output buffer too small (string decode).
18    BufferTooSmall,
19    InvalidUtf8,
20}
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum EncodeError {
24    NotWritable,
25    UnresolvedRef,
26    /// Composed / packed-field windows are read-oriented (§14, §13.1).
27    Unsupported,
28    WrongValueType,
29    BufferTooSmall,
30}
31
32/// §11.4 constraint that a write value violated.
33#[derive(Clone, Copy, Debug, PartialEq, Eq)]
34pub enum ConstraintKind {
35    Min,
36    Max,
37    Step,
38    AllowedValues,
39}
40
41/// Facade error, generic over the transport's error type.
42#[derive(Debug)]
43pub enum Error<T> {
44    Transport(T),
45    DeviceNotFound,
46    PointNotFound,
47    MeasurandNotSupported,
48    /// More than one point matches the measurand query (spec §26.4).
49    AmbiguousMeasurand,
50    /// Composed points via facade, unknown discovery kind, SunS not found…
51    UnsupportedMapping(&'static str),
52    Decode(DecodeError),
53    Encode(EncodeError),
54    WriteAccess,
55    WriteConstraint(ConstraintKind),
56}
57
58impl<T> From<DecodeError> for Error<T> {
59    fn from(e: DecodeError) -> Self {
60        Error::Decode(e)
61    }
62}
63
64impl<T> From<EncodeError> for Error<T> {
65    fn from(e: EncodeError) -> Self {
66        Error::Encode(e)
67    }
68}
69
70impl fmt::Display for DecodeError {
71    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72        match self {
73            DecodeError::UnresolvedRef => write!(f, "scale/selector ref not resolved in context"),
74            DecodeError::ZeroScaleDenominator => write!(f, "scale denominator is zero"),
75            DecodeError::ComposedBaseZero => write!(f, "composed base is zero"),
76            DecodeError::ShortRead => write!(f, "register window shorter than point width"),
77            DecodeError::BufferTooSmall => write!(f, "output buffer too small"),
78            DecodeError::InvalidUtf8 => write!(f, "decoded string is not valid UTF-8"),
79        }
80    }
81}
82
83impl fmt::Display for EncodeError {
84    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85        match self {
86            EncodeError::NotWritable => write!(f, "point is not writable"),
87            EncodeError::UnresolvedRef => write!(f, "scale ref not resolved in context"),
88            EncodeError::Unsupported => write!(f, "value kind is not encodable"),
89            EncodeError::WrongValueType => write!(f, "value type does not match the point"),
90            EncodeError::BufferTooSmall => write!(f, "register buffer too small"),
91        }
92    }
93}
94
95impl fmt::Display for ConstraintKind {
96    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97        match self {
98            ConstraintKind::Min => write!(f, "min_value"),
99            ConstraintKind::Max => write!(f, "max_value"),
100            ConstraintKind::Step => write!(f, "step"),
101            ConstraintKind::AllowedValues => write!(f, "allowed_values"),
102        }
103    }
104}
105
106impl<T: fmt::Display> fmt::Display for Error<T> {
107    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108        match self {
109            Error::Transport(e) => write!(f, "transport: {e}"),
110            Error::DeviceNotFound => write!(f, "device profile not found"),
111            Error::PointNotFound => write!(f, "point not found"),
112            Error::MeasurandNotSupported => write!(f, "measurand not supported"),
113            Error::AmbiguousMeasurand => write!(f, "measurand query is ambiguous"),
114            Error::UnsupportedMapping(d) => write!(f, "unsupported mapping: {d}"),
115            Error::Decode(e) => write!(f, "decode: {e}"),
116            Error::Encode(e) => write!(f, "encode: {e}"),
117            Error::WriteAccess => write!(f, "point is not writable"),
118            Error::WriteConstraint(k) => write!(f, "write violates constraint {k}"),
119        }
120    }
121}
122
123#[cfg(feature = "std")]
124impl std::error::Error for DecodeError {}
125#[cfg(feature = "std")]
126impl std::error::Error for EncodeError {}
127#[cfg(feature = "std")]
128impl<T: fmt::Display + fmt::Debug> std::error::Error for Error<T> {}