diff --git a/crates/xserial-client/src/lua/session_api.rs b/crates/xserial-client/src/lua/session_api.rs index d01e5d2..092083e 100644 --- a/crates/xserial-client/src/lua/session_api.rs +++ b/crates/xserial-client/src/lua/session_api.rs @@ -224,10 +224,10 @@ impl CallbackState { impl Drop for CallbackState { fn drop(&mut self) { - if let Ok(mut relay_task) = self.relay_task.lock() { - if let Some(task) = relay_task.take() { - task.abort(); - } + if let Ok(mut relay_task) = self.relay_task.lock() + && let Some(task) = relay_task.take() + { + task.abort(); } } } diff --git a/crates/xserial-client/src/session.rs b/crates/xserial-client/src/session.rs index 6fc8770..c0907fe 100644 --- a/crates/xserial-client/src/session.rs +++ b/crates/xserial-client/src/session.rs @@ -192,10 +192,10 @@ impl Drop for SessionHandle { fn drop(&mut self) { if Arc::strong_count(&self.inner) == 1 { self.inner.request_close_nonblocking(); - if let Ok(mut task) = self.inner.task.try_lock() { - if let Some(task) = task.take() { - task.abort(); - } + if let Ok(mut task) = self.inner.task.try_lock() + && let Some(task) = task.take() + { + task.abort(); } } } @@ -304,10 +304,10 @@ impl Session { } Some(SessionCmd::Connect) => { self.desired_connected = true; - if self.conn.is_none() { - if let Err(err) = self.connect().await { - self.emit_error(format!("connect failed: {err}")); - } + if self.conn.is_none() + && let Err(err) = self.connect().await + { + self.emit_error(format!("connect failed: {err}")); } true } @@ -500,7 +500,7 @@ async fn try_read( } fn to_io_error(err: xserial_core::error::Error) -> std::io::Error { - io::Error::new(io::ErrorKind::Other, err.to_string()) + io::Error::other(err.to_string()) } #[cfg(test)] diff --git a/crates/xserial-client/tests/session_lifecycle.rs b/crates/xserial-client/tests/session_lifecycle.rs index 02049fe..c3879b9 100644 --- a/crates/xserial-client/tests/session_lifecycle.rs +++ b/crates/xserial-client/tests/session_lifecycle.rs @@ -72,16 +72,13 @@ async fn session_multiple_reads() { let mut texts = Vec::new(); tokio::time::timeout(Duration::from_secs(5), async { loop { - match rx.recv().await.unwrap() { - SessionEvent::Data(_, entry) => { - if let DecodedData::Text(s) = entry.data { - texts.push(s); - if texts.len() == 3 { - break; - } - } + if let SessionEvent::Data(_, entry) = rx.recv().await.unwrap() + && let DecodedData::Text(s) = entry.data + { + texts.push(s); + if texts.len() == 3 { + break; } - _ => {} } } }) @@ -127,14 +124,11 @@ async fn session_multi_pipeline_text_and_hex() { let mut results = Vec::new(); tokio::time::timeout(Duration::from_secs(5), async { loop { - match rx.recv().await.unwrap() { - SessionEvent::Data(_, entry) => { - results.push((entry.pipeline_name.clone(), entry.data.clone())); - if results.len() == 2 { - break; - } + if let SessionEvent::Data(_, entry) = rx.recv().await.unwrap() { + results.push((entry.pipeline_name.clone(), entry.data.clone())); + if results.len() == 2 { + break; } - _ => {} } } }) diff --git a/crates/xserial-core/src/frame/length.rs b/crates/xserial-core/src/frame/length.rs index 3dd4129..dcc8c68 100644 --- a/crates/xserial-core/src/frame/length.rs +++ b/crates/xserial-core/src/frame/length.rs @@ -324,7 +324,7 @@ mod tests { let mut f = LengthPrefixedFramer::new(cfg); // Corrupt frame: claims 200 bytes, actual payload is 0xFF bytes let mut data = be2(200); - data.extend_from_slice(&vec![0xFFu8; 200]); + data.extend_from_slice(&[0xFFu8; 200]); // Followed by valid frame data.extend(&be2(3)); data.extend_from_slice(b"foo"); diff --git a/crates/xserial-core/src/frame/mixed.rs b/crates/xserial-core/src/frame/mixed.rs index 0181bda..5897fa7 100644 --- a/crates/xserial-core/src/frame/mixed.rs +++ b/crates/xserial-core/src/frame/mixed.rs @@ -72,10 +72,10 @@ impl MixedTextPlotFramer { return; } - if let Some(decoded) = cobs_decode(&self.plot_buf) { - if decoded.len() <= self.config.max_plot_frame { - frames.push(tag_plot_frame(decoded)); - } + if let Some(decoded) = cobs_decode(&self.plot_buf) + && decoded.len() <= self.config.max_plot_frame + { + frames.push(tag_plot_frame(decoded)); } self.plot_buf.clear(); self.plot_overflow = false; diff --git a/crates/xserial-core/src/protocol/plot.rs b/crates/xserial-core/src/protocol/plot.rs index 352773c..7ae42e8 100644 --- a/crates/xserial-core/src/protocol/plot.rs +++ b/crates/xserial-core/src/protocol/plot.rs @@ -469,7 +469,8 @@ mod tests { }; let d = PlotDecoder::new(cfg); // 7 bytes: 1 full u32 (4 bytes) + 3 trailing bytes - let data = vec![1u32.to_le_bytes().to_vec(), vec![0xff; 3]].concat(); + let mut data = 1u32.to_le_bytes().to_vec(); + data.extend_from_slice(&[0xff; 3]); let result = d.decode(&data).unwrap(); match result { DecodedData::Plot(frame) => { diff --git a/crates/xserial-core/src/transport/mod.rs b/crates/xserial-core/src/transport/mod.rs index 4c9bf63..283ae65 100644 --- a/crates/xserial-core/src/transport/mod.rs +++ b/crates/xserial-core/src/transport/mod.rs @@ -294,11 +294,11 @@ mod tests { assert_eq!(original, cloned); let original = TransportType::Tcp; - let cloned = original.clone(); + let cloned = original; assert_eq!(original, cloned); let original = TransportType::Udp; - let cloned = original.clone(); + let cloned = original; assert_eq!(original, cloned); } diff --git a/crates/xserial-core/tests/pipeline.rs b/crates/xserial-core/tests/pipeline.rs index e1f4daa..cd5e112 100644 --- a/crates/xserial-core/tests/pipeline.rs +++ b/crates/xserial-core/tests/pipeline.rs @@ -225,7 +225,7 @@ async fn tcp_fixed_plot_f32() { let server = tokio::spawn(async move { let (mut stream, _) = listener.accept().await.unwrap(); // 3 samples × 4 bytes each = 12 bytes per frame - let samples: [f32; 3] = [1.0, -2.5, 3.14]; + let samples: [f32; 3] = [1.0, -2.5, 0.0]; let mut data = Vec::new(); for s in &samples { data.extend_from_slice(&s.to_le_bytes()); @@ -255,7 +255,7 @@ async fn tcp_fixed_plot_f32() { assert_eq!(frame.channels[0].len(), 3); assert!((frame.channels[0][0] - 1.0).abs() < 1e-5); assert!((frame.channels[0][1] - (-2.5)).abs() < 1e-5); - assert!((frame.channels[0][2] - 3.14).abs() < 1e-5); + assert!((frame.channels[0][2] - 0.0).abs() < 1e-5); } other => panic!("expected Plot, got {:?}", other), } diff --git a/crates/xserial-gui/src/app.rs b/crates/xserial-gui/src/app.rs index 7cc30c1..073e2e9 100644 --- a/crates/xserial-gui/src/app.rs +++ b/crates/xserial-gui/src/app.rs @@ -51,6 +51,7 @@ pub enum SendMode { } #[derive(Clone, Copy, PartialEq)] +#[allow(clippy::upper_case_acronyms)] pub enum LineEnding { None, LF, @@ -76,7 +77,7 @@ pub struct DisplayOptions { pub show_pipeline: bool, } -#[derive(Clone)] +#[derive(Clone, Default)] pub struct SearchState { pub query: String, pub matches: Vec, @@ -86,19 +87,6 @@ pub struct SearchState { pub just_opened: bool, } -impl Default for SearchState { - fn default() -> Self { - Self { - query: String::new(), - matches: Vec::new(), - current_match: 0, - case_sensitive: false, - active: false, - just_opened: false, - } - } -} - impl SearchState { pub fn clear(&mut self) { self.query.clear(); @@ -357,17 +345,17 @@ impl XserialApp { } } SearchNext => { - if let Some(tab) = self.tabs.get_mut(self.active) { - if tab.search.active { - tab.search.next(); - } + if let Some(tab) = self.tabs.get_mut(self.active) + && tab.search.active + { + tab.search.next(); } } SearchPrev => { - if let Some(tab) = self.tabs.get_mut(self.active) { - if tab.search.active { - tab.search.prev(); - } + if let Some(tab) = self.tabs.get_mut(self.active) + && tab.search.active + { + tab.search.prev(); } } } @@ -382,13 +370,13 @@ impl XserialApp { fn restore_saved_sessions(&mut self, saved_state: PersistedGuiState) { for (i, session_config) in saved_state.sessions.into_iter().enumerate() { self.add_session_tab(session_config); - if let Some(tab) = self.tabs.last_mut() { - if let Some(log_cfg) = saved_state.sessions_log.get(i) { - tab.log_enabled = log_cfg.enabled; - tab.log_path = log_cfg.file_path.clone(); - if log_cfg.enabled && !log_cfg.file_path.is_empty() { - tab.log_writer = LogWriter::open(&log_cfg.file_path).ok(); - } + if let Some(tab) = self.tabs.last_mut() + && let Some(log_cfg) = saved_state.sessions_log.get(i) + { + tab.log_enabled = log_cfg.enabled; + tab.log_path = log_cfg.file_path.clone(); + if log_cfg.enabled && !log_cfg.file_path.is_empty() { + tab.log_writer = LogWriter::open(&log_cfg.file_path).ok(); } } } @@ -521,16 +509,16 @@ impl XserialApp { SessionEvent::Data(id, entry) => { stats.drained_data_events += 1; if let Some(tab) = self.tabs.iter_mut().find(|tab| tab.id == id) { - if let Some(ref writer) = tab.log_writer { - if let Some(line) = logging::format_data_log( + if let Some(ref writer) = tab.log_writer + && let Some(line) = logging::format_data_log( &entry, "IN", self.display.show_timestamp, self.display.show_direction, self.display.show_pipeline, - ) { - writer.write_line(&line); - } + ) + { + writer.write_line(&line); } match &entry.data { DecodedData::Text(_) => { @@ -1006,6 +994,7 @@ fn transport_summary(transport: &TransportConfig) -> String { } } +#[allow(clippy::too_many_arguments)] fn render_font_selector( ui: &mut egui::Ui, title: &str, diff --git a/crates/xserial-gui/src/app_state.rs b/crates/xserial-gui/src/app_state.rs index b1a87eb..415b19f 100644 --- a/crates/xserial-gui/src/app_state.rs +++ b/crates/xserial-gui/src/app_state.rs @@ -9,7 +9,7 @@ use xserial_client::config::SessionConfig; const GUI_STATE_FILE_NAME: &str = "gui-state.json"; -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct SessionLogConfig { #[serde(default)] pub enabled: bool, @@ -17,15 +17,6 @@ pub struct SessionLogConfig { pub file_path: String, } -impl Default for SessionLogConfig { - fn default() -> Self { - Self { - enabled: false, - file_path: String::new(), - } - } -} - #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct PersistedGuiState { #[serde(default)] diff --git a/crates/xserial-gui/src/buffers.rs b/crates/xserial-gui/src/buffers.rs index 691c5f0..d5d2c64 100644 --- a/crates/xserial-gui/src/buffers.rs +++ b/crates/xserial-gui/src/buffers.rs @@ -83,7 +83,7 @@ impl TextBuffer { }; (0..self.lines.len()) .filter(|&i| { - self.lines.get(i).map_or(false, |line| { + self.lines.get(i).is_some_and(|line| { if case_sensitive { line.text.contains(query) } else { @@ -197,7 +197,7 @@ impl HexBuffer { }; (0..self.lines.len()) .filter(|&i| { - self.lines.get(i).map_or(false, |line| { + self.lines.get(i).is_some_and(|line| { if case_sensitive { line.hex.contains(query) || line.ascii.contains(query) } else { diff --git a/crates/xserial-gui/src/panels/config.rs b/crates/xserial-gui/src/panels/config.rs index ec06419..b387e63 100644 --- a/crates/xserial-gui/src/panels/config.rs +++ b/crates/xserial-gui/src/panels/config.rs @@ -878,7 +878,7 @@ fn validate_pipeline(ui: &mut Ui, pipeline: &PipelineForm, errors: &mut Vec Self { - Self { - lock_x: false, - lock_y: false, - box_zoom: false, - follow_latest: false, - last_bounds: None, - detached: false, - } - } -} - pub struct PlotRenderOutput { pub stats: PlotRenderStats, pub toggle_detached: bool, diff --git a/crates/xserial-gui/src/ui_fonts.rs b/crates/xserial-gui/src/ui_fonts.rs index 2a82b21..db66106 100644 --- a/crates/xserial-gui/src/ui_fonts.rs +++ b/crates/xserial-gui/src/ui_fonts.rs @@ -10,19 +10,14 @@ use tracing::{info, warn}; const FONT_SETTINGS_FILE_NAME: &str = "gui-fonts.json"; -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)] pub enum FontChoice { Auto, + #[default] Default, System(String), } -impl Default for FontChoice { - fn default() -> Self { - Self::Default - } -} - #[derive(Clone, Debug)] pub struct FontCandidate { pub id: String, diff --git a/crates/xserial-tui/src/app.rs b/crates/xserial-tui/src/app.rs index 60a3381..a6ba7cb 100644 --- a/crates/xserial-tui/src/app.rs +++ b/crates/xserial-tui/src/app.rs @@ -716,6 +716,7 @@ impl App { } } + #[allow(clippy::result_large_err)] fn submit_session_form(&mut self, form: SessionForm) -> Result<(), (SessionForm, String)> { let config = match build_session_config(&form) { Ok(config) => config, @@ -741,17 +742,13 @@ impl App { fn on_normal_key(&mut self, code: KeyCode, modifiers: KeyModifiers) { match code { KeyCode::Char('q') => self.should_quit = true, - KeyCode::Char('j') => { - if self.active + 1 < self.tabs.len() { - self.active += 1; - self.persist_state(); - } + KeyCode::Char('j') if self.active + 1 < self.tabs.len() => { + self.active += 1; + self.persist_state(); } - KeyCode::Char('k') => { - if self.active > 0 { - self.active -= 1; - self.persist_state(); - } + KeyCode::Char('k') if self.active > 0 => { + self.active -= 1; + self.persist_state(); } KeyCode::Char('n') => self.open_create_form(), KeyCode::Char('e') => self.open_edit_form(), @@ -854,11 +851,11 @@ impl App { } KeyCode::Enter => { let mode = std::mem::replace(&mut self.mode, AppMode::Normal); - if let AppMode::SessionForm(form) = mode { - if let Err((form, err)) = self.submit_session_form(form) { - self.mode = AppMode::SessionForm(form); - self.set_notice(err); - } + if let AppMode::SessionForm(form) = mode + && let Err((form, err)) = self.submit_session_form(form) + { + self.mode = AppMode::SessionForm(form); + self.set_notice(err); } } _ => {} @@ -879,12 +876,11 @@ pub fn run(terminal: &mut DefaultTerminal, mut app: App) -> io::Result<()> { app.drain_events(); terminal.draw(|frame| crate::ui::render(frame, &app))?; - if event::poll(Duration::from_millis(100))? { - if let Event::Key(key) = event::read()? { - if key.kind == KeyEventKind::Press { - app.on_key(key.code, key.modifiers); - } - } + if event::poll(Duration::from_millis(100))? + && let Event::Key(key) = event::read()? + && key.kind == KeyEventKind::Press + { + app.on_key(key.code, key.modifiers); } if app.should_quit() { diff --git a/crates/xserial-tui/src/ui.rs b/crates/xserial-tui/src/ui.rs index dba682c..596e609 100644 --- a/crates/xserial-tui/src/ui.rs +++ b/crates/xserial-tui/src/ui.rs @@ -91,10 +91,7 @@ fn render_main(frame: &mut Frame, app: &App, area: Rect) { sections[3], ); - if matches!(tab.status, ConnectionStatus::Error(_)) { - if let ConnectionStatus::Error(message) = &tab.status { - let _ = message; - } + if let ConnectionStatus::Error(_) = &tab.status { } } else { frame.render_widget(