1use std::fmt;
7
8#[derive(Debug)]
10pub enum Error {
11 PermissionDenied { path: String },
13 DeviceNotFound { path: String },
15 MissingReport { report_name: String },
17 LampIdMismatch { expected: u16, got: u16 },
19 LampIdOutOfRange { lamp_id: u16, lamp_count: u16 },
21 DuplicateLampId { lamp_id: u16 },
23 NoAutonomousMode,
25 NoMultiUpdate,
27 TruncatedReport {
29 report_name: &'static str,
30 expected: usize,
31 got: usize,
32 },
33 UnsupportedReportType,
35 InvalidArgument(String),
37 Io(std::io::Error),
39 Arg(lexopt::Error),
41}
42
43impl fmt::Display for Error {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 match self {
46 Self::PermissionDenied { path } => {
47 write!(f, "Permission denied on {path}")
48 }
49 Self::DeviceNotFound { path } => {
50 write!(f, "Device not found: {path}")
51 }
52 Self::MissingReport { report_name } => {
53 write!(f, "Device has no '{report_name}' report")
54 }
55 Self::LampIdMismatch { expected, got } => {
56 write!(
57 f,
58 "LampAttributesResponse returned LampId {got}, expected {expected}"
59 )
60 }
61 Self::LampIdOutOfRange {
62 lamp_id,
63 lamp_count,
64 } => {
65 write!(f, "LampId {lamp_id} exceeds device LampCount {lamp_count}")
66 }
67 Self::DuplicateLampId { lamp_id } => {
68 write!(f, "Duplicate LampId {lamp_id} in update request")
69 }
70 Self::NoAutonomousMode => {
71 write!(
72 f,
73 "This device does not support autonomous mode. \
74 Only LampArray (Usage Page 0x59) devices have this feature."
75 )
76 }
77 Self::NoMultiUpdate => {
78 write!(
79 f,
80 "Per-lamp color control requires a LampArray device (Usage Page 0x59) \
81 with a LampMultiUpdateReport."
82 )
83 }
84 Self::TruncatedReport {
85 report_name,
86 expected,
87 got,
88 } => {
89 write!(
90 f,
91 "Truncated {report_name} report: expected at least {expected} bytes, got {got}"
92 )
93 }
94 Self::UnsupportedReportType => {
95 write!(f, "Cannot write to an Input report (device-to-host only)")
96 }
97 Self::InvalidArgument(msg) => {
98 write!(f, "{msg}")
99 }
100 Self::Io(e) => write!(f, "{e}"),
101 Self::Arg(e) => write!(f, "{e}"),
102 }
103 }
104}
105
106impl std::error::Error for Error {
107 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
108 match self {
109 Self::Io(e) => Some(e),
110 Self::Arg(e) => Some(e),
111 _ => None,
112 }
113 }
114}
115
116impl From<std::io::Error> for Error {
117 fn from(e: std::io::Error) -> Self {
118 Self::Io(e)
119 }
120}
121
122impl From<lexopt::Error> for Error {
123 fn from(e: lexopt::Error) -> Self {
124 Self::Arg(e)
125 }
126}
127
128pub type Result<T> = std::result::Result<T, Error>;