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}