Skip to content

Commit c8f9d02

Browse files
authored
refactor(Device): Add error propagation and remove .unwraps() where applicable
refactor(Device): Add error propagation and remove .unwraps() where applicable
2 parents 599e557 + d8cc2d3 commit c8f9d02

File tree

3 files changed

+114
-88
lines changed

3 files changed

+114
-88
lines changed

twinleaf-tools/src/bin/tio-monitor.rs

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -215,17 +215,16 @@ fn main() {
215215
};
216216

217217
let proxy = tio::proxy::Interface::new(&root);
218-
let mut device = twinleaf::Device::open(&proxy, route);
218+
let mut device = twinleaf::Device::open(&proxy, route)
219+
.expect("Failed to open device. Check connection and permissions.");
219220

220221
let mut stdout = std::io::stdout();
221-
if let Ok(()) = terminal_setup(&stdout) {
222-
std::panic::set_hook(Box::new(|_| {
223-
terminal_teardown(&std::io::stdout());
224-
}));
225-
} else {
226-
terminal_teardown(&stdout);
227-
return;
228-
}
222+
terminal_setup(&stdout).expect("Failed to setup terminal");
223+
let original_hook = std::panic::take_hook();
224+
std::panic::set_hook(Box::new(move |panic_info| {
225+
terminal_teardown(&std::io::stdout());
226+
original_hook(panic_info);
227+
}));
229228

230229
let mut wait_until = Instant::now();
231230
let mut width: usize = 0;
@@ -237,37 +236,37 @@ fn main() {
237236
std::thread::sleep(sleep_time);
238237
wait_until = now + sleep_time + Duration::from_millis(50);
239238

240-
loop {
241-
use crossterm::event::*;
242-
match poll(Duration::from_secs(0)) {
243-
Ok(false) => {
244-
break;
245-
}
246-
Ok(true) => match read() {
247-
Ok(Event::Key(key_event)) => {
248-
if key_event.code == KeyCode::Char('q')
249-
|| key_event.code == KeyCode::Esc
250-
|| (key_event.code == KeyCode::Char('c')
251-
&& key_event.modifiers == KeyModifiers::CONTROL)
252-
{
253-
break 'drawing;
254-
}
255-
}
256-
Ok(_) => {}
257-
Err(_) => {
239+
if crossterm::event::poll(Duration::from_secs(0)).unwrap_or(false) {
240+
match crossterm::event::read() {
241+
Ok(crossterm::event::Event::Key(key)) => {
242+
use crossterm::event::{KeyCode, KeyModifiers};
243+
if key.code == KeyCode::Char('q')
244+
|| key.code == KeyCode::Esc
245+
|| (key.code == KeyCode::Char('c') && key.modifiers == KeyModifiers::CONTROL)
246+
{
258247
break 'drawing;
259248
}
260-
},
261-
Err(_) => {
262-
break 'drawing;
263249
}
250+
Err(_) => break 'drawing,
251+
_ => {}
264252
}
265253
}
266254

267255
let mut recompute_width = false;
268-
while let Some(sample) = device.try_next() {
269-
recompute_width = recompute_width || sample.meta_changed;
270-
last_sample.insert(sample.stream.as_ref().stream_id, (sample, now));
256+
loop {
257+
match device.try_next() {
258+
Ok(Some(sample)) => {
259+
recompute_width = recompute_width || sample.meta_changed;
260+
last_sample.insert(sample.stream.as_ref().stream_id, (sample, now));
261+
}
262+
Ok(None) => {
263+
break;
264+
}
265+
Err(e) => {
266+
eprintln!("\nError receiving data from device: {:?}. Exiting.", e);
267+
break 'drawing;
268+
}
269+
}
271270
}
272271
if recompute_width {
273272
for (_, (sample, _)) in &last_sample {

twinleaf-tools/src/bin/tio-tool.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -347,9 +347,14 @@ fn meta_dump(args: &[String]) -> Result<(), ()> {
347347
let (_matches, root, route) = tio_parseopts(&opts, args);
348348

349349
let proxy = proxy::Interface::new(&root);
350-
let mut device = twinleaf::Device::open(&proxy, route);
350+
let mut device = twinleaf::Device::open(&proxy, route).map_err(|e| {
351+
eprintln!("Failed to open device: {:?}", e);
352+
})?;
353+
354+
let meta = device.get_metadata().map_err(|e| {
355+
eprintln!("Failed to get metadata: {:?}", e);
356+
})?;
351357

352-
let meta = device.get_metadata();
353358
println!("{:?}", meta.device);
354359
for (_id, stream) in meta.streams {
355360
println!("{:?}", stream.stream);
@@ -380,12 +385,20 @@ fn data_dump(args: &[String]) -> Result<(), ()> {
380385
let (_matches, root, route) = tio_parseopts(&opts, args);
381386

382387
let proxy = proxy::Interface::new(&root);
383-
let mut device = twinleaf::Device::open(&proxy, route);
388+
let mut device = twinleaf::Device::open(&proxy, route).map_err(|e| {
389+
eprintln!("Failed to open device: {:?}", e);
390+
})?;
384391

385392
loop {
386-
print_sample(&device.next());
393+
match device.next() {
394+
Ok(sample) => print_sample(&sample),
395+
Err(e) => {
396+
eprintln!("\nDevice error: {:?}. Exiting.", e);
397+
break;
398+
}
399+
}
387400
}
388-
// Ok(())
401+
Ok(())
389402
}
390403

391404
fn log(args: &[String]) -> Result<(), ()> {
@@ -443,9 +456,14 @@ fn log_metadata(args: &[String]) -> Result<(), ()> {
443456
}
444457

445458
let proxy = proxy::Interface::new(&root);
446-
let mut device = twinleaf::Device::open(&proxy, route);
447-
448-
let meta = device.get_metadata();
459+
let mut device = twinleaf::Device::open(&proxy, route).map_err(|e| {
460+
eprintln!("Failed to open device: {:?}", e);
461+
})?;
462+
463+
let meta = device.get_metadata().map_err(|e| {
464+
eprintln!("Failed to get metadata: {:?}", e);
465+
})?;
466+
449467
let output_path = if let Some(path) = matches.opt_str("f") {
450468
path
451469
} else {

twinleaf/src/device/mod.rs

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,20 @@ impl Device {
2222
}
2323
}
2424

25-
pub fn open(proxy: &tio::proxy::Interface, route: DeviceRoute) -> Device {
26-
let port = proxy.device_full(route).unwrap(); // TODO
27-
Self::new(port)
25+
pub fn open(proxy: &tio::proxy::Interface, route: DeviceRoute) -> Result<Device, proxy::PortError> {
26+
let port = proxy.device_full(route)?;
27+
Ok(Self::new(port))
2828
}
2929

30-
fn internal_rpcs(&mut self) {
30+
fn internal_rpcs(&mut self) -> Result<(), proxy::SendError> {
3131
if self.n_reqs == 0 {
3232
let reqs = self.parser.requests();
3333
for req in reqs {
34-
self.dev_port.send(req).unwrap();
34+
self.dev_port.send(req)?;
3535
self.n_reqs += 1;
3636
}
3737
}
38+
Ok(())
3839
}
3940

4041
fn process_packet(&mut self, pkt: tio::Packet) -> Option<tio::Packet> {
@@ -61,70 +62,71 @@ impl Device {
6162
None
6263
}
6364

64-
pub fn get_metadata(&mut self) -> DeviceFullMetadata {
65+
pub fn get_metadata(&mut self) -> Result<DeviceFullMetadata, tio::proxy::RpcError> {
6566
loop {
6667
if self.n_reqs == 0 {
6768
match self.parser.get_metadata() {
68-
Ok(full_meta) => return full_meta,
69+
Ok(full_meta) => return Ok(full_meta),
6970
Err(reqs) => {
7071
for req in reqs {
71-
self.dev_port.send(req).unwrap();
72+
self.dev_port.send(req).map_err(tio::proxy::RpcError::SendFailed)?;
7273
self.n_reqs += 1;
7374
}
7475
}
7576
}
7677
}
77-
let pkt = self.dev_port.recv().unwrap();
78+
let pkt = self.dev_port.recv().map_err(tio::proxy::RpcError::RecvFailed)?;
7879
self.process_packet(pkt);
7980
}
8081
}
8182

82-
pub fn next(&mut self) -> Sample {
83+
pub fn next(&mut self) -> Result<Sample, tio::proxy::RpcError> {
8384
loop {
8485
if !self.sample_queue.is_empty() {
85-
return self.sample_queue.pop_front().unwrap();
86+
return Ok(self.sample_queue.pop_front().unwrap());
8687
}
8788

88-
self.internal_rpcs();
89-
let pkt = self.dev_port.recv().expect("no packet in blocking recv");
89+
self.internal_rpcs().map_err(tio::proxy::RpcError::SendFailed)?;
90+
91+
let pkt = self.dev_port.recv().map_err(tio::proxy::RpcError::RecvFailed)?;
9092
self.process_packet(pkt);
9193
}
9294
}
9395

94-
pub fn try_next(&mut self) -> Option<Sample> {
96+
pub fn try_next(&mut self) -> Result<Option<Sample>, tio::proxy::RpcError> {
9597
loop {
9698
if !self.sample_queue.is_empty() {
97-
return self.sample_queue.pop_front();
99+
return Ok(self.sample_queue.pop_front());
98100
}
99101

100-
self.internal_rpcs();
101-
self.process_packet(match self.dev_port.try_recv() {
102+
self.internal_rpcs().map_err(tio::proxy::RpcError::SendFailed)?;
103+
104+
let pkt = match self.dev_port.try_recv() {
102105
Ok(pkt) => pkt,
103-
Err(proxy::RecvError::WouldBlock) => {
104-
return None;
105-
}
106-
_ => {
107-
panic!("receive error");
108-
}
109-
});
106+
Err(proxy::RecvError::WouldBlock) => return Ok(None),
107+
Err(e) => return Err(tio::proxy::RpcError::RecvFailed(e)),
108+
};
109+
self.process_packet(pkt);
110110
}
111111
}
112112

113-
pub fn drain(&mut self) -> Vec<Sample> {
113+
pub fn drain(&mut self) -> Result<Vec<Sample>, tio::proxy::RpcError> {
114114
loop {
115-
self.internal_rpcs();
116-
self.process_packet(match self.dev_port.try_recv() {
117-
Ok(pkt) => pkt,
115+
self.internal_rpcs().map_err(tio::proxy::RpcError::SendFailed)?;
116+
match self.dev_port.try_recv() {
117+
Ok(pkt) => {
118+
self.process_packet(pkt);
119+
}
118120
Err(proxy::RecvError::WouldBlock) => {
119121
break;
120122
}
121-
_ => {
122-
panic!("receive error");
123+
Err(e) => {
124+
return Err(tio::proxy::RpcError::RecvFailed(e));
123125
}
124-
});
126+
}
125127
}
126-
127-
self.sample_queue.drain(0..).collect()
128+
129+
Ok(self.sample_queue.drain(0..).collect())
128130
}
129131

130132
pub fn raw_rpc(&mut self, name: &str, arg: &[u8]) -> Result<Vec<u8>, tio::proxy::RpcError> {
@@ -137,15 +139,19 @@ impl Device {
137139
return Err(tio::proxy::RpcError::SendFailed(err));
138140
}
139141
loop {
140-
self.internal_rpcs();
141-
let pkt = self.dev_port.recv().expect("no packet in blocking recv");
142+
self.internal_rpcs().map_err(tio::proxy::RpcError::SendFailed)?;
143+
let pkt = match self.dev_port.recv() {
144+
Ok(packet) => packet,
145+
Err(e) => return Err(tio::proxy::RpcError::RecvFailed(e)),
146+
};
147+
142148
if let Some(pkt) = self.process_packet(pkt) {
143149
match pkt.payload {
144150
tio::proto::Payload::RpcReply(rep) => return Ok(rep.reply),
145151
tio::proto::Payload::RpcError(err) => {
146152
return Err(tio::proxy::RpcError::ExecError(err))
147153
}
148-
_ => panic!("unexpected"),
154+
_ => unreachable!("process_packet returned a non-RPC packet to raw_rpc"),
149155
}
150156
}
151157
}
@@ -176,29 +182,32 @@ impl Device {
176182
self.rpc(name, ())
177183
}
178184

179-
pub fn get_multi(&mut self, name: &str) -> Vec<u8> {
185+
pub fn get_multi(&mut self, name: &str) -> Result<Vec<u8>, tio::proxy::RpcError> {
180186
let mut full_reply = vec![];
181187

182188
for i in 0u16..=65535u16 {
183189
match self.raw_rpc(&name, &i.to_le_bytes().to_vec()) {
184190
Ok(mut rep) => full_reply.append(&mut rep),
185-
Err(proxy::RpcError::ExecError(err)) => {
186-
if let tio::proto::RpcErrorCode::InvalidArgs = err.error {
187-
break;
188-
} else {
189-
panic!("RPC error");
191+
Err(err @ proxy::RpcError::ExecError(_)) => {
192+
if let proxy::RpcError::ExecError(payload) = &err {
193+
if let tio::proto::RpcErrorCode::InvalidArgs = payload.error {
194+
break;
195+
}
190196
}
197+
return Err(err);
191198
}
192-
_ => {
193-
panic!("RPC error")
199+
Err(e) => {
200+
return Err(e);
194201
}
195202
}
196203
}
197204

198-
full_reply
205+
Ok(full_reply)
199206
}
200207

201-
pub fn get_multi_str(&mut self, name: &str) -> String {
202-
String::from_utf8_lossy(&self.get_multi(name)).to_string()
208+
pub fn get_multi_str(&mut self, name: &str) -> Result<String, tio::proxy::RpcError> {
209+
let reply_bytes = self.get_multi(name)?;
210+
let result_string = String::from_utf8_lossy(&reply_bytes).to_string();
211+
Ok(result_string)
203212
}
204213
}

0 commit comments

Comments
 (0)