From a0cb336368110183dcc8be051e6dbf887ae718bf Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Thu, 28 Sep 2023 10:08:54 +0200 Subject: [PATCH] tacd: error propagation instead of unwraping part 1 Instead of unwrapping Results and potentially panicking we replace it with proper error propagation that can be acted upon in the future e.g. return different exit codes for systemd or display error messages. Signed-off-by: Stefan Kerkmann --- src/adc.rs | 20 +++++------ src/dbus.rs | 18 +++++----- src/digital_io.rs | 28 +++++++-------- src/digital_io/gpio/demo_mode.rs | 24 ++++--------- src/digital_io/gpio/test.rs | 2 +- src/dut_power.rs | 58 +++++++++++++++----------------- src/http_server.rs | 35 ++++++++++--------- src/led.rs | 16 +++++---- src/main.rs | 8 ++--- src/measurement.rs | 35 ++++++++++++------- src/ui.rs | 3 +- src/watchdog.rs | 12 +++---- 12 files changed, 131 insertions(+), 128 deletions(-) diff --git a/src/adc.rs b/src/adc.rs index f2c79247..634dc624 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -83,7 +83,7 @@ impl Adc { let adc = Self { usb_host_curr: AdcChannel { - fast: stm32_thread.clone().get_channel("usb-host-curr").unwrap(), + fast: stm32_thread.clone().get_channel("usb-host-curr")?, topic: bb.topic( "/v1/usb/host/total/feedback/current", true, @@ -94,7 +94,7 @@ impl Adc { ), }, usb_host1_curr: AdcChannel { - fast: stm32_thread.clone().get_channel("usb-host1-curr").unwrap(), + fast: stm32_thread.clone().get_channel("usb-host1-curr")?, topic: bb.topic( "/v1/usb/host/port1/feedback/current", true, @@ -105,7 +105,7 @@ impl Adc { ), }, usb_host2_curr: AdcChannel { - fast: stm32_thread.clone().get_channel("usb-host2-curr").unwrap(), + fast: stm32_thread.clone().get_channel("usb-host2-curr")?, topic: bb.topic( "/v1/usb/host/port2/feedback/current", true, @@ -116,7 +116,7 @@ impl Adc { ), }, usb_host3_curr: AdcChannel { - fast: stm32_thread.clone().get_channel("usb-host3-curr").unwrap(), + fast: stm32_thread.clone().get_channel("usb-host3-curr")?, topic: bb.topic( "/v1/usb/host/port3/feedback/current", true, @@ -127,7 +127,7 @@ impl Adc { ), }, out0_volt: AdcChannel { - fast: stm32_thread.clone().get_channel("out0-volt").unwrap(), + fast: stm32_thread.clone().get_channel("out0-volt")?, topic: bb.topic( "/v1/output/out_0/feedback/voltage", true, @@ -138,7 +138,7 @@ impl Adc { ), }, out1_volt: AdcChannel { - fast: stm32_thread.clone().get_channel("out1-volt").unwrap(), + fast: stm32_thread.clone().get_channel("out1-volt")?, topic: bb.topic( "/v1/output/out_1/feedback/voltage", true, @@ -149,7 +149,7 @@ impl Adc { ), }, iobus_curr: AdcChannel { - fast: stm32_thread.clone().get_channel("iobus-curr").unwrap(), + fast: stm32_thread.clone().get_channel("iobus-curr")?, topic: bb.topic( "/v1/iobus/feedback/current", true, @@ -160,7 +160,7 @@ impl Adc { ), }, iobus_volt: AdcChannel { - fast: stm32_thread.clone().get_channel("iobus-volt").unwrap(), + fast: stm32_thread.clone().get_channel("iobus-volt")?, topic: bb.topic( "/v1/iobus/feedback/voltage", true, @@ -171,7 +171,7 @@ impl Adc { ), }, pwr_volt: AdcChannel { - fast: powerboard_thread.clone().get_channel("pwr-volt").unwrap(), + fast: powerboard_thread.clone().get_channel("pwr-volt")?, topic: bb.topic( "/v1/dut/feedback/voltage", true, @@ -182,7 +182,7 @@ impl Adc { ), }, pwr_curr: AdcChannel { - fast: powerboard_thread.get_channel("pwr-curr").unwrap(), + fast: powerboard_thread.get_channel("pwr-curr")?, topic: bb.topic( "/v1/dut/feedback/current", true, diff --git a/src/dbus.rs b/src/dbus.rs index a8e8872a..38a0c28b 100644 --- a/src/dbus.rs +++ b/src/dbus.rs @@ -15,6 +15,7 @@ // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +use anyhow::Result; use async_std::sync::Arc; use crate::broker::{BrokerBuilder, Topic}; @@ -22,7 +23,7 @@ use crate::led::BlinkPattern; #[cfg(feature = "demo_mode")] mod zb { - pub type Result = std::result::Result; + use anyhow::Result; pub struct Connection; pub struct ConnectionBuilder; @@ -51,7 +52,7 @@ mod zb { pub use zbus::*; } -use zb::{Connection, ConnectionBuilder, Result}; +use zb::{Connection, ConnectionBuilder}; pub mod networkmanager; pub mod rauc; @@ -76,20 +77,17 @@ impl DbusSession { bb: &mut BrokerBuilder, led_dut: Arc>, led_uplink: Arc>, - ) -> Self { + ) -> Result { let tacd = Tacd::new(); - let conn_builder = ConnectionBuilder::system() - .unwrap() - .name("de.pengutronix.tacd") - .unwrap(); + let conn_builder = ConnectionBuilder::system()?.name("de.pengutronix.tacd")?; - let conn = Arc::new(tacd.serve(conn_builder).build().await.unwrap()); + let conn = Arc::new(tacd.serve(conn_builder).build().await?); - Self { + Ok(Self { network: Network::new(bb, &conn, led_dut, led_uplink), rauc: Rauc::new(bb, &conn), systemd: Systemd::new(bb, &conn).await, - } + }) } } diff --git a/src/digital_io.rs b/src/digital_io.rs index 63eb9c7e..2eabbd2e 100644 --- a/src/digital_io.rs +++ b/src/digital_io.rs @@ -15,6 +15,7 @@ // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +use anyhow::{Context, Result}; use async_std::prelude::*; use async_std::sync::Arc; use async_std::task::spawn; @@ -58,27 +59,26 @@ fn handle_line_wo( initial: bool, inverted: bool, led_topic: Option>>, -) -> Arc> { +) -> Result>> { let topic = bb.topic_rw(path, Some(initial)); - let line = find_line(line_name).unwrap(); - let dst = line - .request(LineRequestFlags::OUTPUT, (initial ^ inverted) as _, "tacd") - .unwrap(); + let line = find_line(line_name).with_context(|| format!("couldn't find line {line_name}"))?; + let dst = line.request(LineRequestFlags::OUTPUT, (initial ^ inverted) as _, "tacd")?; let (mut src, _) = topic.clone().subscribe_unbounded(); spawn(async move { while let Some(ev) = src.next().await { - dst.set_value((ev ^ inverted) as _).unwrap(); + dst.set_value((ev ^ inverted) as _)?; if let Some(led) = &led_topic { let pattern = BlinkPattern::solid(if ev { 1.0 } else { 0.0 }); led.set(pattern); } } + anyhow::Ok(()) }); - topic + Ok(topic) } impl DigitalIo { @@ -86,7 +86,7 @@ impl DigitalIo { bb: &mut BrokerBuilder, led_0: Arc>, led_1: Arc>, - ) -> Self { + ) -> Result { let out_0 = handle_line_wo( bb, "/v1/output/out_0/asserted", @@ -94,7 +94,7 @@ impl DigitalIo { false, false, Some(led_0), - ); + )?; let out_1 = handle_line_wo( bb, @@ -103,16 +103,16 @@ impl DigitalIo { false, false, Some(led_1), - ); + )?; - let uart_rx_en = handle_line_wo(bb, "/v1/uart/rx/enabled", "UART_RX_EN", true, true, None); - let uart_tx_en = handle_line_wo(bb, "/v1/uart/tx/enabled", "UART_TX_EN", true, true, None); + let uart_rx_en = handle_line_wo(bb, "/v1/uart/rx/enabled", "UART_RX_EN", true, true, None)?; + let uart_tx_en = handle_line_wo(bb, "/v1/uart/tx/enabled", "UART_TX_EN", true, true, None)?; - Self { + Ok(Self { out_0, out_1, uart_rx_en, uart_tx_en, - } + }) } } diff --git a/src/digital_io/gpio/demo_mode.rs b/src/digital_io/gpio/demo_mode.rs index 1c438a3d..26b90c68 100644 --- a/src/digital_io/gpio/demo_mode.rs +++ b/src/digital_io/gpio/demo_mode.rs @@ -27,33 +27,23 @@ pub struct LineHandle { } impl LineHandle { - pub fn set_value(&self, val: u8) -> Result<(), ()> { + pub fn set_value(&self, val: u8) -> Result<()> { // This does not actually set up any IIO things. // It is just a hack to let adc/iio/demo_mode.rs // communicate with this function so that toggling an output // has an effect on the measured values. - let iio_thread_stm32 = block_on(IioThread::new_stm32()).unwrap(); - let iio_thread_pwr = block_on(IioThread::new_powerboard()).unwrap(); + let iio_thread_stm32 = block_on(IioThread::new_stm32())?; + let iio_thread_pwr = block_on(IioThread::new_powerboard())?; match self.name.as_str() { - "OUT_0" => iio_thread_stm32 - .get_channel("out0-volt") - .unwrap() - .set(val != 0), - "OUT_1" => iio_thread_stm32 - .get_channel("out1-volt") - .unwrap() - .set(val != 0), + "OUT_0" => iio_thread_stm32.get_channel("out0-volt")?.set(val != 0), + "OUT_1" => iio_thread_stm32.get_channel("out1-volt")?.set(val != 0), "DUT_PWR_EN" => { iio_thread_pwr .clone() - .get_channel("pwr-curr") - .unwrap() - .set(val == 0); - iio_thread_pwr - .get_channel("pwr-volt") - .unwrap() + .get_channel("pwr-curr")? .set(val == 0); + iio_thread_pwr.get_channel("pwr-volt")?.set(val == 0); } _ => {} } diff --git a/src/digital_io/gpio/test.rs b/src/digital_io/gpio/test.rs index d67a8ca7..27d8a918 100644 --- a/src/digital_io/gpio/test.rs +++ b/src/digital_io/gpio/test.rs @@ -33,7 +33,7 @@ pub struct LineHandle { } impl LineHandle { - pub fn set_value(&self, val: u8) -> Result<(), ()> { + pub fn set_value(&self, val: u8) -> Result<()> { println!("GPIO simulation set {} to {}", self.name, val); self.val.store(val, Ordering::Relaxed); Ok(()) diff --git a/src/dut_power.rs b/src/dut_power.rs index c9376886..f75ecb1a 100644 --- a/src/dut_power.rs +++ b/src/dut_power.rs @@ -19,7 +19,7 @@ use std::sync::atomic::{AtomicU32, AtomicU8, Ordering}; use std::thread; use std::time::{Duration, Instant}; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context, Result}; use async_std::channel::bounded; use async_std::prelude::*; use async_std::sync::{Arc, Weak}; @@ -44,13 +44,13 @@ mod prio { mod prio { use std::convert::TryFrom; - use anyhow::{anyhow, Result}; + use anyhow::{anyhow, Error, Result}; use thread_priority::*; pub fn realtime_priority() -> Result<()> { set_thread_priority_and_policy( thread_native_id(), - ThreadPriority::Crossplatform(ThreadPriorityValue::try_from(10).unwrap()), + ThreadPriority::Crossplatform(ThreadPriorityValue::try_from(10).map_err(Error::msg)?), ThreadSchedulePolicy::Realtime(RealtimeThreadSchedulePolicy::Fifo), ) .map_err(|e| anyhow!("Failed to set up realtime priority {e:?}")) @@ -236,10 +236,11 @@ fn turn_off_with_reason( pwr_line: &LineHandle, discharge_line: &LineHandle, fail_state: &AtomicU8, -) { - pwr_line.set_value(1 - PWR_LINE_ASSERTED).unwrap(); - discharge_line.set_value(DISCHARGE_LINE_ASSERTED).unwrap(); +) -> Result<()> { + pwr_line.set_value(1 - PWR_LINE_ASSERTED)?; + discharge_line.set_value(DISCHARGE_LINE_ASSERTED)?; fail_state.store(reason as u8, Ordering::Relaxed); + Ok(()) } /// Labgrid has a fixed assumption of how a REST based power port should work. @@ -334,14 +335,12 @@ impl DutPwrThread { let request = Arc::new(AtomicU8::new(OutputRequest::Idle as u8)); let state = Arc::new(AtomicU8::new(OutputState::Off as u8)); - thread_res_tx - .try_send(Ok((tick, request.clone(), state.clone()))) - .unwrap(); + thread_res_tx.try_send(Ok((tick, request.clone(), state.clone())))?; (tick_weak, request, state) } Err(e) => { - thread_res_tx.try_send(Err(e)).unwrap(); + thread_res_tx.try_send(Err(e))?; panic!() } }; @@ -378,7 +377,7 @@ impl DutPwrThread { &pwr_line, &discharge_line, &state, - ); + )?; } else { // We have a fresh ADC value. Signal "everything is well" // to the watchdog task. @@ -415,7 +414,7 @@ impl DutPwrThread { &pwr_line, &discharge_line, &state, - ); + )?; continue; } @@ -429,7 +428,7 @@ impl DutPwrThread { &pwr_line, &discharge_line, &state, - ); + )?; continue; } @@ -442,7 +441,7 @@ impl DutPwrThread { &pwr_line, &discharge_line, &state, - ); + )?; continue; } @@ -452,32 +451,31 @@ impl DutPwrThread { match req { OutputRequest::Idle => {} OutputRequest::On => { - discharge_line - .set_value(1 - DISCHARGE_LINE_ASSERTED) - .unwrap(); - pwr_line.set_value(PWR_LINE_ASSERTED).unwrap(); + discharge_line.set_value(1 - DISCHARGE_LINE_ASSERTED)?; + pwr_line.set_value(PWR_LINE_ASSERTED)?; state.store(OutputState::On as u8, Ordering::Relaxed); } OutputRequest::Off => { - discharge_line.set_value(DISCHARGE_LINE_ASSERTED).unwrap(); - pwr_line.set_value(1 - PWR_LINE_ASSERTED).unwrap(); + discharge_line.set_value(DISCHARGE_LINE_ASSERTED)?; + pwr_line.set_value(1 - PWR_LINE_ASSERTED)?; state.store(OutputState::Off as u8, Ordering::Relaxed); } OutputRequest::OffFloating => { - discharge_line - .set_value(1 - DISCHARGE_LINE_ASSERTED) - .unwrap(); - pwr_line.set_value(1 - PWR_LINE_ASSERTED).unwrap(); + discharge_line.set_value(1 - DISCHARGE_LINE_ASSERTED)?; + pwr_line.set_value(1 - PWR_LINE_ASSERTED)?; state.store(OutputState::OffFloating as u8, Ordering::Relaxed); } } } // Make sure to enter fail safe mode before leaving the thread - turn_off_with_reason(OutputState::Off, &pwr_line, &discharge_line, &state); + turn_off_with_reason(OutputState::Off, &pwr_line, &discharge_line, &state) })?; - let (tick, request, state) = thread_res_rx.next().await.unwrap()?; + let (tick, request, state) = thread_res_rx + .next() + .await + .context("didn't receive thread result")??; // The request and state topic use the same external path, this way one // can e.g. publish "On" to the topic and be sure that the output is @@ -572,12 +570,12 @@ mod tests { #[test] fn failsafe() { - let pwr_line = find_line("DUT_PWR_EN").unwrap(); - let discharge_line = find_line("DUT_PWR_DISCH").unwrap(); + let pwr_line = find_line("DUT_PWR_EN").expect("couldn't find DUT_PWR_EN"); + let discharge_line = find_line("DUT_PWR_DISCH").expect("couldn't find DUT_PWR_DISCH"); let (adc, dut_pwr, led) = { let mut bb = BrokerBuilder::new(); - let adc = block_on(Adc::new(&mut bb)).unwrap(); + let adc = block_on(Adc::new(&mut bb)).expect("couldn't create ADC"); let led = Topic::anonymous(None); let dut_pwr = block_on(DutPwrThread::new( @@ -586,7 +584,7 @@ mod tests { adc.pwr_curr.clone(), led.clone(), )) - .unwrap(); + .expect("couldn't start DUT PWR thread"); (adc, dut_pwr, led) }; diff --git a/src/http_server.rs b/src/http_server.rs index 94d1a7be..a662ca96 100644 --- a/src/http_server.rs +++ b/src/http_server.rs @@ -18,6 +18,7 @@ use std::fs::write; use std::net::TcpListener; +use anyhow::{Context, Result}; use tide::{Body, Response, Server}; mod serve_dir; @@ -60,30 +61,30 @@ pub struct HttpServer { } impl HttpServer { - pub fn new() -> Self { - let mut this = Self { + pub fn new() -> Result { + let mut server = Self { listeners: Vec::new(), server: tide::new(), }; // Open [::]:80 / [::]:8080. This, somewhat confusingly also listens on // 0.0.0.0 and not only on IPv6. - this.listeners.push( - TcpListener::bind(FALLBACK_PORT).expect( - "Could not bind web API to port, is there already another service running?", - ), - ); + server + .listeners + .push(TcpListener::bind(FALLBACK_PORT).with_context(|| { + "Could not bind web API to port, is there already another service running?" + })?); - this.expose_openapi_json(); - this.expose_dir(WEBUI_DIR, "/", false); - this.expose_dir(EXTRA_DIR, "/srv", true); + server.expose_openapi_json(); + server.expose_dir(WEBUI_DIR, "/", false); + server.expose_dir(EXTRA_DIR, "/srv", true); for (fs_path, web_path) in EXPOSED_FILES_RW { let fs_path = FS_PREFIX.to_owned() + *fs_path; - this.expose_file_rw(fs_path, web_path); + server.expose_file_rw(fs_path, web_path)?; } - this + Ok(server) } /// Serve a compiled-in openapi.json file @@ -109,8 +110,8 @@ impl HttpServer { } /// Serve a file from disk for reading and writing - fn expose_file_rw(&mut self, fs_path: String, web_path: &str) { - self.server.at(web_path).serve_file(&fs_path).unwrap(); + fn expose_file_rw(&mut self, fs_path: String, web_path: &str) -> Result<()> { + self.server.at(web_path).serve_file(&fs_path)?; self.server .at(web_path) @@ -124,9 +125,11 @@ impl HttpServer { Ok(Response::new(204)) } }); + Ok(()) } - pub async fn serve(self) -> Result<(), std::io::Error> { - self.server.listen(self.listeners).await + pub async fn serve(self) -> Result<()> { + self.server.listen(self.listeners).await?; + Ok(()) } } diff --git a/src/led.rs b/src/led.rs index 1d76dd46..3bf532dc 100644 --- a/src/led.rs +++ b/src/led.rs @@ -17,6 +17,7 @@ use std::io::ErrorKind; +use anyhow::Result; use async_std::prelude::*; use async_std::sync::Arc; use async_std::task::spawn; @@ -91,7 +92,7 @@ fn handle_color( bb: &mut BrokerBuilder, hardware_name: &'static str, topic_name: &'static str, -) -> Arc> { +) -> Result>> { let topic = bb.topic_ro(&format!("/v1/tac/led/{topic_name}/color"), None); if let Some(led) = get_led_checked(hardware_name) { @@ -99,7 +100,7 @@ fn handle_color( spawn(async move { while let Some((r, g, b)) = rx.next().await { - let max = led.max_brightness().unwrap(); + let max = led.max_brightness()?; // I've encountered LEDs staying off when set to the max value, // but setting them to (max - 1) turned them on. @@ -109,22 +110,23 @@ fn handle_color( warn!("Failed to set LED color: {}", e); } } + anyhow::Ok(()) }); } - topic + Ok(topic) } impl Led { - pub fn new(bb: &mut BrokerBuilder) -> Self { - Self { + pub fn new(bb: &mut BrokerBuilder) -> Result { + Ok(Self { out_0: handle_pattern(bb, "tac:green:out0", "out_0"), out_1: handle_pattern(bb, "tac:green:out1", "out_1"), dut_pwr: handle_pattern(bb, "tac:green:dutpwr", "dut_pwr"), eth_dut: handle_pattern(bb, "tac:green:statusdut", "eth_dut"), eth_lab: handle_pattern(bb, "tac:green:statuslab", "eth_lab"), status: handle_pattern(bb, "rgb:status", "status"), - status_color: handle_color(bb, "rgb:status", "status"), - } + status_color: handle_color(bb, "rgb:status", "status")?, + }) } } diff --git a/src/main.rs b/src/main.rs index 0ad4f181..33d5c39f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -68,7 +68,7 @@ async fn main() -> Result<()> { // Expose hardware on the TAC via the broker framework. let backlight = Backlight::new(&mut bb)?; - let led = Led::new(&mut bb); + let led = Led::new(&mut bb)?; let adc = Adc::new(&mut bb).await?; let dut_pwr = DutPwrThread::new( &mut bb, @@ -77,7 +77,7 @@ async fn main() -> Result<()> { led.dut_pwr.clone(), ) .await?; - let dig_io = DigitalIo::new(&mut bb, led.out_0.clone(), led.out_1.clone()); + let dig_io = DigitalIo::new(&mut bb, led.out_0.clone(), led.out_1.clone())?; let regulators = Regulators::new(&mut bb); let temperatures = Temperatures::new(&mut bb); let usb_hub = UsbHub::new(&mut bb); @@ -91,7 +91,7 @@ async fn main() -> Result<()> { adc.iobus_volt.fast.clone(), ); let (network, rauc, systemd) = { - let dbus = DbusSession::new(&mut bb, led.eth_dut.clone(), led.eth_lab.clone()).await; + let dbus = DbusSession::new(&mut bb, led.eth_dut.clone(), led.eth_lab.clone()).await?; (dbus.network, dbus.rauc, dbus.systemd) }; @@ -107,7 +107,7 @@ async fn main() -> Result<()> { // Set up a http server and provide some static files like the web // interface and config files that may be edited inside the web ui. - let mut http_server = HttpServer::new(); + let mut http_server = HttpServer::new()?; // Allow editing some aspects of the TAC configuration when in "setup mode". let setup_mode = SetupMode::new(&mut bb, &mut http_server.server); diff --git a/src/measurement.rs b/src/measurement.rs index 3d403e1b..85d1c309 100644 --- a/src/measurement.rs +++ b/src/measurement.rs @@ -18,6 +18,7 @@ use std::ops::{Deref, DerefMut}; use std::time::{Instant, SystemTime}; +use anyhow::{Context, Result}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[derive(Debug, Clone, Copy)] @@ -57,9 +58,11 @@ impl Timestamp { /// /// The idea is to take the current Instant (monotonic time) and System Time /// (calendar time) and calculate: now_system - (now_instant - ts_instant). - pub fn in_system_time(&self) -> SystemTime { + pub fn in_system_time(&self) -> Result { let age = self.0.elapsed(); - SystemTime::now().checked_sub(age).unwrap() + SystemTime::now() + .checked_sub(age) + .with_context(|| "couldn't get system time") } } @@ -80,25 +83,33 @@ impl DerefMut for Timestamp { impl Serialize for Timestamp { /// Serialize an Instant as a javascript timestamp (f64 containing the number /// of milliseconds since Unix Epoch 0). - fn serialize(&self, serializer: S) -> Result + fn serialize(&self, serializer: S) -> std::result::Result where S: Serializer, { - let age_as_sys = self.in_system_time(); - let timestamp = age_as_sys.duration_since(SystemTime::UNIX_EPOCH).unwrap(); - let js_timestamp = 1000.0 * timestamp.as_secs_f64(); - js_timestamp.serialize(serializer) + use serde::ser::Error; + match { + || { + let time = self.in_system_time()?; + let timestamp = time.duration_since(SystemTime::UNIX_EPOCH)?; + let js_timestamp = 1000.0 * timestamp.as_secs_f64(); + anyhow::Ok(js_timestamp) + } + }() { + Ok(timestamp) => timestamp.serialize(serializer), + Err(e) => Err(Error::custom(format!( + "failed to serialize Timestamp with {e}" + ))), + } } } impl<'d> Deserialize<'d> for Timestamp { - fn deserialize(deserializer: D) -> Result + fn deserialize(_: D) -> Result where D: Deserializer<'d>, { - let _js_timestamp = f64::deserialize(deserializer)?; - // We need both Serialize and Deserialize for Topics, even when they - // are never deserialized in practice like Timestamps. - unimplemented!(); + use serde::de::Error; + Err(Error::custom("unused implementation")) } } diff --git a/src/ui.rs b/src/ui.rs index 648151b1..e6535aac 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -17,6 +17,7 @@ use std::time::Duration; +use anyhow::Result; use async_std::prelude::*; use async_std::sync::Arc; use async_std::task::spawn; @@ -176,7 +177,7 @@ impl Ui { } } - pub async fn run(mut self, display: Display) -> Result<(), std::io::Error> { + pub async fn run(mut self, display: Display) -> Result<()> { let (mut screen_rx, _) = self.screen.clone().subscribe_unbounded(); let (mut alerts_rx, _) = self.alerts.clone().subscribe_unbounded(); let (mut button_events, _) = self.buttons.clone().subscribe_unbounded(); diff --git a/src/watchdog.rs b/src/watchdog.rs index e1581234..f9ea1c6e 100644 --- a/src/watchdog.rs +++ b/src/watchdog.rs @@ -15,16 +15,17 @@ // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -use std::io::{Error, ErrorKind, Result}; +use std::io::{Error, ErrorKind}; use std::time::Duration; +use anyhow::Result; use async_std::task::sleep; use crate::dut_power::TickReader; #[cfg(any(test, feature = "demo_mode"))] mod sd { - use std::io::Result; + use anyhow::Result; pub const STATE_READY: () = (); pub const STATE_WATCHDOG: () = (); @@ -84,10 +85,9 @@ impl Watchdog { notify(false, [(STATE_WATCHDOG, "trigger")].iter())?; - break Err(Error::new( - ErrorKind::TimedOut, - "Power Thread stalled for too long", - )); + break Err( + Error::new(ErrorKind::TimedOut, "Power Thread stalled for too long").into(), + ); } notify(false, [(STATE_WATCHDOG, "1")].iter())?;