1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use thiserror::Error;
use crate::ua;
/// Result type used in this crate.
pub type Result<T> = std::result::Result<T, Error>;
/// Error type used in this crate.
///
/// This error may be returned from many different OPC UA calls. It represents any status code
/// that doesn't qualify as [`is_good()`].
///
/// [`is_good()`]: crate::ua::StatusCode::is_good
#[derive(Debug, Error)]
#[expect(clippy::error_impl_error, reason = "main error type")]
pub enum Error {
/// Error from server.
#[error("{0}")]
Server(ua::StatusCode),
/// Internal error.
#[error("{0}")]
Internal(&'static str),
}
impl Error {
/// Creates error from status code.
///
/// To avoid confusion, the status code should be considered bad or uncertain but not good, as
/// indicated by [`ua::StatusCode::is_good()`].
#[must_use]
pub(crate) fn new(status_code: ua::StatusCode) -> Self {
debug_assert!(!status_code.is_good());
Self::Server(status_code)
}
pub(crate) fn verify_good(status_code: &ua::StatusCode) -> Result<()> {
if status_code.is_good() {
Ok(())
} else {
Err(Self::new(status_code.clone()))
}
}
/// Gets associated OPC UA status code.
///
/// This returns the original status code except for internal errors where the generic status
/// code [`ua::StatusCode::BAD`] is returned instead.
#[must_use]
pub fn status_code(&self) -> ua::StatusCode {
match self {
// TODO: Avoid clone and make `ua::StatusCode` derive `Copy`.
Error::Server(status_code) => status_code.clone(),
Error::Internal(_) => ua::StatusCode::BAD,
}
}
#[must_use]
pub(crate) const fn internal(message: &'static str) -> Self {
Self::Internal(message)
}
}