diff --git a/lact-cli/src/lib.rs b/lact-cli/src/lib.rs index 1b82f79..d2b1c6b 100644 --- a/lact-cli/src/lib.rs +++ b/lact-cli/src/lib.rs @@ -19,8 +19,8 @@ pub fn run(args: CliArgs) -> Result<()> { } async fn list_gpus(_: &CliArgs, client: &DaemonClient) -> Result<()> { - let buffer = client.list_devices().await?; - for entry in buffer.inner()? { + let entries = client.list_devices().await?; + for entry in entries { let id = entry.id; if let Some(name) = entry.name { println!("{id} ({name})"); @@ -33,8 +33,7 @@ async fn list_gpus(_: &CliArgs, client: &DaemonClient) -> Result<()> { async fn info(args: &CliArgs, client: &DaemonClient) -> Result<()> { for id in extract_gpu_ids(args, client).await { - let info_buffer = client.get_device_info(&id).await?; - let info = info_buffer.inner()?; + let info = client.get_device_info(&id).await?; let pci_info = info.pci_info.context("GPU reports no pci info")?; if let Some(ref vendor) = pci_info.device_pci_info.vendor { @@ -56,10 +55,8 @@ async fn extract_gpu_ids(args: &CliArgs, client: &DaemonClient) -> Vec { match args.gpu_id { Some(ref id) => vec![id.clone()], None => { - let buffer = client.list_devices().await.expect("Could not list GPUs"); - buffer - .inner() - .expect("Could not deserialize GPUs response") + let entries = client.list_devices().await.expect("Could not list GPUs"); + entries .into_iter() .map(|entry| entry.id.to_owned()) .collect() @@ -68,8 +65,7 @@ async fn extract_gpu_ids(args: &CliArgs, client: &DaemonClient) -> Vec { } async fn snapshot(client: &DaemonClient) -> Result<()> { - let buffer = client.generate_debug_snapshot().await?; - let path = buffer.inner()?; + let path = client.generate_debug_snapshot().await?; println!("Generated debug snapshot in {path}"); Ok(()) } diff --git a/lact-client/src/lib.rs b/lact-client/src/lib.rs index 7d57b2c..92a63ad 100644 --- a/lact-client/src/lib.rs +++ b/lact-client/src/lib.rs @@ -16,10 +16,9 @@ use schema::{ ClocksInfo, DeviceInfo, DeviceListEntry, DeviceStats, FanOptions, PowerStates, ProfilesInfo, Request, Response, SystemInfo, }; -use serde::Deserialize; +use serde::de::DeserializeOwned; use std::{ - future::Future, marker::PhantomData, os::unix::net::UnixStream, path::PathBuf, pin::Pin, - rc::Rc, time::Duration, + future::Future, os::unix::net::UnixStream, path::PathBuf, pin::Pin, rc::Rc, time::Duration, }; use tokio::{ net::ToSocketAddrs, @@ -73,19 +72,24 @@ impl DaemonClient { self.status_tx.subscribe() } - fn make_request<'a, 'r, T: Deserialize<'r>>( + fn make_request<'a, T: DeserializeOwned>( &'a self, request: Request<'a>, - ) -> Pin>> + 'a>> { + ) -> Pin> + 'a>> { Box::pin(async { let mut stream = self.stream.lock().await; let request_payload = serde_json::to_string(&request)?; match stream.request(&request_payload).await { - Ok(response_payload) => Ok(ResponseBuffer { - buf: response_payload, - _phantom: PhantomData, - }), + Ok(response_payload) => { + let response: Response = serde_json::from_str(&response_payload) + .context("Could not deserialize response from daemon")?; + match response { + Response::Ok(data) => Ok(data), + Response::Error(err) => Err(anyhow::Error::new(err) + .context("Got error from daemon, end of client boundary")), + } + } Err(err) => { error!("Could not make request: {err}, reconnecting to socket"); let _ = self.status_tx.send(ConnectionStatusMsg::Disconnected); @@ -113,20 +117,16 @@ impl DaemonClient { }) } - pub async fn list_devices(&self) -> anyhow::Result>> { + pub async fn list_devices(&self) -> anyhow::Result> { self.make_request(Request::ListDevices).await } pub async fn set_fan_control(&self, cmd: FanOptions<'_>) -> anyhow::Result { - self.make_request(Request::SetFanControl(cmd)) - .await? - .inner() + self.make_request(Request::SetFanControl(cmd)).await } pub async fn set_power_cap(&self, id: &str, cap: Option) -> anyhow::Result { - self.make_request(Request::SetPowerCap { id, cap }) - .await? - .inner() + self.make_request(Request::SetPowerCap { id, cap }).await } request_plain!(get_system_info, SystemInfo, SystemInfo); @@ -148,38 +148,31 @@ impl DaemonClient { pub async fn list_profiles(&self, include_state: bool) -> anyhow::Result { self.make_request(Request::ListProfiles { include_state }) - .await? - .inner() + .await } pub async fn set_profile(&self, name: Option, auto_switch: bool) -> anyhow::Result<()> { self.make_request(Request::SetProfile { name, auto_switch }) - .await? - .inner() + .await } pub async fn create_profile(&self, name: String, base: ProfileBase) -> anyhow::Result<()> { self.make_request(Request::CreateProfile { name, base }) - .await? - .inner() + .await } pub async fn delete_profile(&self, name: String) -> anyhow::Result<()> { - self.make_request(Request::DeleteProfile { name }) - .await? - .inner() + self.make_request(Request::DeleteProfile { name }).await } pub async fn move_profile(&self, name: String, new_position: usize) -> anyhow::Result<()> { self.make_request(Request::MoveProfile { name, new_position }) - .await? - .inner() + .await } pub async fn evaluate_profile_rule(&self, rule: ProfileRule) -> anyhow::Result { self.make_request(Request::EvaluateProfileRule { rule }) - .await? - .inner() + .await } pub async fn set_profile_rule( @@ -188,8 +181,7 @@ impl DaemonClient { rule: Option, ) -> anyhow::Result<()> { self.make_request(Request::SetProfileRule { name, rule }) - .await? - .inner() + .await } pub async fn set_performance_level( @@ -201,8 +193,7 @@ impl DaemonClient { id, performance_level, }) - .await? - .inner() + .await } pub async fn set_clocks_value( @@ -211,8 +202,7 @@ impl DaemonClient { command: SetClocksCommand, ) -> anyhow::Result { self.make_request(Request::SetClocksValue { id, command }) - .await? - .inner() + .await } pub async fn batch_set_clocks_value( @@ -221,8 +211,7 @@ impl DaemonClient { commands: Vec, ) -> anyhow::Result { self.make_request(Request::BatchSetClocksValue { id, commands }) - .await? - .inner() + .await } pub async fn set_enabled_power_states( @@ -232,8 +221,7 @@ impl DaemonClient { states: Vec, ) -> anyhow::Result { self.make_request(Request::SetEnabledPowerStates { id, kind, states }) - .await? - .inner() + .await } pub async fn set_power_profile_mode( @@ -247,14 +235,12 @@ impl DaemonClient { index, custom_heuristics, }) - .await? - .inner() + .await } pub async fn confirm_pending_config(&self, command: ConfirmCommand) -> anyhow::Result<()> { self.make_request(Request::ConfirmPendingConfig(command)) - .await? - .inner() + .await } } @@ -275,25 +261,6 @@ fn get_socket_path() -> Option { } } -pub struct ResponseBuffer { - buf: String, - _phantom: PhantomData, -} - -impl<'a, T: Deserialize<'a>> ResponseBuffer { - pub fn inner(&'a self) -> anyhow::Result { - let response: Response = serde_json::from_str(&self.buf) - .context("Could not deserialize response from daemon")?; - match response { - Response::Ok(data) => Ok(data), - Response::Error(err) => { - Err(anyhow::Error::new(err) - .context("Got error from daemon, end of client boundary")) - } - } - } -} - #[derive(Debug, Clone, Copy)] pub enum ConnectionStatusMsg { Disconnected, diff --git a/lact-client/src/macros.rs b/lact-client/src/macros.rs index c14ca0b..e3b1f16 100644 --- a/lact-client/src/macros.rs +++ b/lact-client/src/macros.rs @@ -1,6 +1,6 @@ macro_rules! request_with_id { ($name:ident, $variant:ident, $response:ty) => { - pub async fn $name(&self, id: &str) -> anyhow::Result> { + pub async fn $name(&self, id: &str) -> anyhow::Result<$response> { self.make_request(Request::$variant { id }).await } }; @@ -8,7 +8,7 @@ macro_rules! request_with_id { macro_rules! request_plain { ($name:ident, $variant:ident, $response:ty) => { - pub async fn $name(&self) -> anyhow::Result> { + pub async fn $name(&self) -> anyhow::Result<$response> { self.make_request(Request::$variant).await } }; diff --git a/lact-gui/src/app.rs b/lact-gui/src/app.rs index 74cde1e..6d3428e 100644 --- a/lact-gui/src/app.rs +++ b/lact-gui/src/app.rs @@ -161,17 +161,15 @@ impl AsyncComponent for AppModel { register_actions(&sender); - let system_info_buf = daemon_client + let system_info = daemon_client .get_system_info() .await .expect("Could not fetch system info"); - let system_info = system_info_buf.inner().expect("Invalid system info buffer"); - let devices_buf = daemon_client + let devices = daemon_client .list_devices() .await .expect("Could not list devices"); - let devices = devices_buf.inner().expect("Could not access devices"); if system_info.version != GUI_VERSION || system_info.commit.as_deref() != Some(GIT_COMMIT) { let err = anyhow!("Version mismatch between GUI and daemon ({GUI_VERSION}-{GIT_COMMIT} vs {}-{})! If you have updated LACT, you need to restart the service with `sudo systemctl restart lactd`.", system_info.version, system_info.commit.as_deref().unwrap_or_default()); @@ -449,7 +447,7 @@ impl AppModel { .get_device_info(&gpu_id) .await .context("Could not fetch info")?; - let info = Arc::new(info_buf.inner()?); + let info = Arc::new(info_buf); // Plain `nvidia` means that the nvidia driver is loaded, but it does not contain a version fetched from NVML if info.driver == "nvidia" { @@ -492,8 +490,7 @@ impl AppModel { .daemon_client .get_device_stats(&gpu_id) .await - .context("Could not fetch stats")? - .inner()?; + .context("Could not fetch stats")?; let stats = Arc::new(stats); self.oc_page.set_stats(&stats, true); @@ -502,13 +499,7 @@ impl AppModel { self.info_page.emit(PageUpdate::Stats(stats)); let maybe_clocks_table = match self.daemon_client.get_device_clocks_info(&gpu_id).await { - Ok(clocks_buf) => match clocks_buf.inner() { - Ok(info) => info.table, - Err(err) => { - debug!("could not extract clocks info: {err:?}"); - None - } - }, + Ok(info) => info.table, Err(err) => { debug!("could not fetch clocks info: {err:?}"); None @@ -521,13 +512,7 @@ impl AppModel { .get_device_power_profile_modes(&gpu_id) .await { - Ok(buf) => match buf.inner() { - Ok(table) => Some(table), - Err(err) => { - debug!("Could not extract profile modes table: {err:?}"); - None - } - }, + Ok(buf) => Some(buf), Err(err) => { debug!("Could not get profile modes table: {err:?}"); None @@ -537,12 +522,7 @@ impl AppModel { .performance_frame .set_power_profile_modes(maybe_modes_table); - match self - .daemon_client - .get_power_states(&gpu_id) - .await - .and_then(|states| states.inner()) - { + match self.daemon_client.get_power_states(&gpu_id).await { Ok(power_states) => { self.oc_page .power_states_frame @@ -773,12 +753,7 @@ impl AppModel { } async fn dump_vbios(&self, gpu_id: &str, root: >k::ApplicationWindow) { - match self - .daemon_client - .dump_vbios(gpu_id) - .await - .and_then(|response| response.inner()) - { + match self.daemon_client.dump_vbios(gpu_id).await { Ok(vbios_data) => { let file_chooser = FileChooserDialog::new( Some("Save VBIOS file"), @@ -826,12 +801,7 @@ impl AppModel { } async fn generate_debug_snapshot(&self, root: >k::ApplicationWindow) { - match self - .daemon_client - .generate_debug_snapshot() - .await - .and_then(|response| response.inner()) - { + match self.daemon_client.generate_debug_snapshot().await { Ok(path) => { let path_label = gtk::Label::builder() .use_markup(true) @@ -968,11 +938,7 @@ fn start_stats_update_loop( loop { tokio::time::sleep(duration).await; - match daemon_client - .get_device_stats(&gpu_id) - .await - .and_then(|buffer| buffer.inner()) - { + match daemon_client.get_device_stats(&gpu_id).await { Ok(stats) => { sender.input(AppMsg::Stats(Arc::new(stats))); } @@ -1043,15 +1009,9 @@ async fn toggle_overdrive(daemon_client: &DaemonClient, enable: bool, root: Appl dialog.show(); let result = if enable { - daemon_client - .enable_overdrive() - .await - .and_then(|buffer| buffer.inner()) + daemon_client.enable_overdrive().await } else { - daemon_client - .disable_overdrive() - .await - .and_then(|buffer| buffer.inner()) + daemon_client.disable_overdrive().await }; dialog.hide();