Skip to content

refactor(script-rs): idiomatic Rust, better error handling, doc comments, SIGINT cleanup#24

Merged
rayworks merged 4 commits into
masterfrom
copilot/refine-rust-script
Apr 14, 2026
Merged

refactor(script-rs): idiomatic Rust, better error handling, doc comments, SIGINT cleanup#24
rayworks merged 4 commits into
masterfrom
copilot/refine-rust-script

Conversation

Copilot AI commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

The script-rs CLI had several code-quality issues: &String params, empty-string sentinels, repeated env::args() reads per call, bare unwrap() on I/O, and String::from("x") + &y concatenation.

src/main.rs

  • Serial number extracted once in main as Option<&str> and threaded through all helpers; serial_checked_command now accepts serial: Option<&str> instead of re-reading env::args() on every invocation
  • locate_apk_pathOption<String> — replaces the empty-string sentinel with a proper None return
  • &String&str in all function signatures
  • open_browser(port, serial) — accepts parameters instead of re-reading args
  • format! everywhere — replaces String::from("x") + &y and the redundant println!("{}", format!(…))
  • split_once(':') — replaces the fragile .split(":").last()
  • Descriptive expect messages on every I/O .unwrap()
  • /// doc comments added to every top-level function
  • Removed the redundant use webbrowser; bare import
  • SIGINT handler cleans up port forward exclusivelysetup_signal_handler accepts port: String and serial: Option<String>, moves them into a dedicated background thread, and invokes unforward_connection on Ctrl-C. The handler is registered in main after forward_connection (to avoid spurious cleanup on early exits) and is the sole place unforward_connection is called. The thread processes exactly one SIGINT via signals.forever().next() and then returns. setup_signal_handler returns (thread::JoinHandle<()>, Handle) — after startup_service_and_wait, main calls signals_close.close() to unblock the thread on a normal exit and then signal_handle.join() to wait for cleanup in both the SIGINT and clean-exit paths.
// Before
fn forward_connection(port: &String) {
    let grp = String::from("tcp:") + &port;
    serial_checked_command().args().output().expect();
}

// After
fn forward_connection(port: &str, serial: Option<&str>) {
    let grp = format!("tcp:{}", port);
    serial_checked_command(serial).args().output().expect();
}

Cargo.toml

  • Added description and repository fields; dropped the vacuous authors = []
Original prompt

Overview

Refine the Rust script located in the script-rs/ directory (script-rs/src/main.rs and script-rs/Cargo.toml). The goal is to improve code quality, idiomatic Rust usage, error handling, and maintainability without changing the core behavior of the program.

Current code

The current script-rs/src/main.rs has these issues:

  1. Clippy / idiomatic Rust warnings:

    • port.trim().parse::<u32>().expect(...) — the parsed value is discarded; it should validate via a proper error message or be stored.
    • Functions take port: &String instead of the idiomatic port: &str.
    • raw_path.split(":").last() — use splitn or direct strip_prefix for clarity.
    • String::from("tcp:") + &port — use format! consistently.
    • String::from("CLASSPATH=") + &(raw_path.to_string()) — use format!.
    • use webbrowser; at the top is an unnecessary bare use (the crate is invoked as webbrowser::open).
    • The open_browser function re-reads env::args() instead of accepting the needed values as parameters.
    • count_connected_devices uses .unwrap() without any error context.
    • Inline format string in println!("{}", format!(...)) — should be println!("{}", ...) directly.
  2. Error handling:

    • Many .unwrap() calls in I/O paths (adb command output, UTF-8 conversion) should use expect with a descriptive message or be propagated via Result.
    • locate_apk_path returns an empty String as a sentinel for failure; this should return Option<String> or Result<String, ...>.
  3. Code organisation / readability:

    • serial_checked_command() reads env::args() on every call; the serial number should be extracted once in main and passed around.
    • The startup_service_and_wait function name is slightly misleading; it also spawns the process. A doc comment would help.
    • Add brief doc comments (///) to each public/top-level function explaining what it does.
  4. Cargo.toml:

    • Add description, authors (can be left empty [] as a placeholder), and repository fields to the [package] section to silence cargo publish warnings and improve discoverability.
    • Consider whether edition = "2021" deps are up-to-date (bump webbrowser and signal-hook to their latest compatible versions if newer ones exist).

Expected changes

  • Refactor functions to accept &str instead of &String where appropriate.
  • Replace sentinel empty-string returns with Option<String>.
  • Extract the serial-number argument into main and pass it to helper functions rather than re-reading env::args() each time.
  • Replace String::from("x") + &y patterns with format!("x{}", y).
  • Remove the redundant use webbrowser; statement (keep the call site webbrowser::open).
  • Add expect messages to .unwrap() calls that touch external process output.
  • Add brief /// doc comments to each function.
  • Update Cargo.toml with description and tidy up formatting.

Please make all these refinements in a single commit on a new branch and open a pull request against master.

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: Create a PR to refine the Rust script under the folder script-rs in the repo DroidCast

Assistant: Now I have a thorough understanding of the Rust code. Let me create a PR with meaningful refinements.

Assistant: We're waiting for your response to the tool call dialog to continue — please accept or reject the request to let me proceed with creating the pull request.

This pull request was created from Copilot chat.

Copilot AI changed the title [WIP] Refine Rust script for improved code quality and maintainability refactor(script-rs): idiomatic Rust, better error handling, doc comments Apr 13, 2026
Copilot AI requested a review from rayworks April 13, 2026 06:50
Comment thread script-rs/src/main.rs
/// main thread is not interrupted.
fn setup_signal_handler() -> Result<(), Box<dyn Error>> {
let mut signals = Signals::new(&[SIGINT])?;
let mut signals = Signals::new([SIGINT])?;

@rayworks rayworks Apr 13, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main thread should be interrupted at this time. So can you call unforward_connection method when receiving the SIGINT signal ?
@copilot

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in f0b9cb1. setup_signal_handler now accepts port: String and serial: Option<String>, moves them into the handler thread, and calls unforward_connection on SIGINT. The call is placed in main right after forward_connection, so the handler only runs cleanup for a forward that was actually established.

@rayworks rayworks marked this pull request as ready for review April 13, 2026 13:58
Copilot AI changed the title refactor(script-rs): idiomatic Rust, better error handling, doc comments refactor(script-rs): idiomatic Rust, better error handling, doc comments, SIGINT cleanup Apr 13, 2026
Copilot AI requested a review from rayworks April 13, 2026 14:07
Comment thread script-rs/src/main.rs Outdated

// unforward
unforward_connection(&port);
unforward_connection(port, serial);

@rayworks rayworks Apr 14, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This redundant call should be removed since it will be called in the signal handler.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in 629c813. Cleanup is now exclusively the signal handler's responsibility.

Comment thread script-rs/src/main.rs Outdated
let mut signals = Signals::new([SIGINT])?;

thread::spawn(move || {
for sig in signals.forever() {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once received the SIGINT, the thread should return, with a JoinHandle waiting for the thread exit.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 629c813. setup_signal_handler now returns (thread::JoinHandle<()>, Handle). The thread uses signals.forever().next() — it processes one SIGINT and then returns. In main, after startup_service_and_wait, signals_close.close() is called (unblocks the thread on a normal exit) and signal_handle.join() waits for it to finish in both the SIGINT and normal-exit paths.

…INT with JoinHandle

Agent-Logs-Url: https://github.com/rayworks/DroidCast/sessions/486e392b-0cac-4f4e-b726-26b846266b47

Co-authored-by: rayworks <1329281+rayworks@users.noreply.github.com>
Copilot AI requested a review from rayworks April 14, 2026 01:50
@rayworks rayworks merged commit 7779f8e into master Apr 14, 2026
@rayworks rayworks deleted the copilot/refine-rust-script branch April 14, 2026 02:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants