Skip to main content

viva_genapi/
error.rs

1//! Error types for GenApi operations.
2
3use thiserror::Error;
4
5/// Error type produced by GenApi operations.
6#[derive(Debug, Error)]
7#[non_exhaustive]
8pub enum GenApiError {
9    /// The requested node does not exist in the nodemap.
10    #[error("node not found: {0}")]
11    NodeNotFound(String),
12    /// The node exists but has a different type.
13    #[error("type mismatch for node: {0}")]
14    Type(String),
15    /// The node access mode forbids the attempted operation.
16    #[error("access denied for node: {0}")]
17    Access(String),
18    /// The node declares `pIsLocked` and the device currently reports it
19    /// locked, so the write was refused locally.
20    ///
21    /// Names the locking feature, because that is the actionable part: a
22    /// caller told only "access denied" has nowhere to go, whereas
23    /// "`ExposureTime` is locked by `ExposureTime_Lck`" points at the feature
24    /// to change first. See ADR-0018 and backlog GA-06.
25    #[error("node {name} is locked by {locked_by}")]
26    Locked {
27        /// The node whose write was refused.
28        name: String,
29        /// The feature named by this node's `pIsLocked`.
30        locked_by: String,
31    },
32    /// The provided value violates the limits declared by the node.
33    #[error("range error for node: {0}")]
34    Range(String),
35    /// The node is currently hidden by selector state.
36    #[error("node unavailable: {0}")]
37    Unavailable(String),
38    /// Underlying register IO failed.
39    #[error("io error: {0}")]
40    Io(String),
41    /// Node metadata or conversion failed.
42    #[error("parse error: {0}")]
43    Parse(String),
44    /// A declaration this crate has no builder for.
45    ///
46    /// [`viva_genapi_xml::NodeDecl`] is `#[non_exhaustive]`, so a node type
47    /// added to the XML layer no longer breaks this crate's *build*. It
48    /// surfaces here instead, at nodemap construction, and lands in
49    /// [`crate::NodeMap::skipped`] where the corpus test will see it.
50    #[error("unsupported node declaration: {0}")]
51    Unsupported(String),
52    /// Parsing a SwissKnife expression failed.
53    #[error("failed to parse expression for {name}: {msg}")]
54    ExprParse { name: String, msg: String },
55    /// Evaluating a SwissKnife expression failed at runtime.
56    #[error("failed to evaluate expression for {name}: {msg}")]
57    ExprEval { name: String, msg: String },
58    /// A SwissKnife expression referenced an unknown variable.
59    #[error("unknown variable '{var}' referenced by {name}")]
60    UnknownVariable { name: String, var: String },
61    /// Raw register value did not correspond to any enum entry.
62    #[error("enum {node} has no entry for raw value {value}")]
63    EnumValueUnknown { node: String, value: i64 },
64    /// Attempted to select an enum entry that does not exist.
65    #[error("enum {node} has no entry named {entry}")]
66    EnumNoSuchEntry { node: String, entry: String },
67    /// Indirect addressing resolved to an invalid register.
68    #[error("node {name} resolved invalid indirect address {addr:#X}")]
69    BadIndirectAddress { name: String, addr: i64 },
70    /// Bitfield metadata exceeded the backing register width.
71    #[error(
72        "bitfield for node {name} exceeds register length {len} (offset {bit_offset}, length {bit_length})"
73    )]
74    BitfieldOutOfRange {
75        name: String,
76        bit_offset: u16,
77        bit_length: u16,
78        len: usize,
79    },
80    /// Provided value does not fit into the declared bitfield.
81    #[error("value {value} too wide for {bit_length}-bit field on node {name}")]
82    ValueTooWide {
83        name: String,
84        value: i64,
85        bit_length: u16,
86    },
87}