Rewrite in Rust

· rtnF


Recently, I saw several good publicity regarding Rust, for example :

A good publicity so intense that i'm quite inclined to join this bandwagon.


Runtime Error? #

Several years ago, I made a Python-based simple timer app to track my own work-hour. Nowadays, I still use this app daily to measure my productivity rate. But, lately, this app has been crashing sporadically for some unknown reason.

Maybe it's a good time to finally rewrite this app for good, in Rust!


Prepare the dependencies #

First, cargo new appname. It will generate two important file : Cargo.toml and main.rs. Open Cargo.toml, add several dependencies.

[dependencies]
console = "0.15.2"
chrono = "0.4"
cli-clipboard = "0.3.0"

Run cargo build to install the dependencies. Then open main.rs, and let's go.

Program structure #

There are two main sections : module inclusion and main function.

use std::thread;
use std::time::{Duration};
use std::io;
use chrono;
use std::sync::mpsc::{self, TryRecvError};
use cli_clipboard::{ClipboardContext, ClipboardProvider};

fn main() {
   // main program
}

Main program : how it works #

Split the app into two thread : backend-timer and frontend. Backend-timer will continue counting the elapsed time in the background. Frontend will wait for quit signal from user. If the frontend received the quit signal, frontend will send a quit message to backend. Backend will reply with the elapsed time data before killing itself.

 1    // Get start timestamp
 2    let date = chrono::Local::now().format("%-d %B %Y").to_string();
 3    let start_time = chrono::Local::now().format("%-H:%M").to_string();
 4    println!("reitnorF timer 2.0");
 5    println!("{}, {}", date,start_time);
 6    println!("");
 7
 8    //Initialize communication channel
 9    let (tx, rx) = mpsc::channel();
10    let (txa, rxa) = mpsc::channel();
11
12    //Initialize time counter
13    let mut i = 1;
14    let mut m = 0;
15    let mut h = 0;
16    
17    //Spawn backend thread
18    thread::spawn(move || {
19        loop {
20            //Update current elapsed time
21            let term = console::Term::stdout();
22            term.clear_last_lines(1).expect("");
23            let stamp = format!("{} hour, {} minute, {} second ",h,m,i);
24            term.write_line(&stamp).expect("");
25           
26            //Second to hour-minute-second conversion
27            thread::sleep(Duration::from_millis(1000));
28            i = i + 1;
29            if i == 60 {i = 0;m = m +1;}
30            if m == 60{m = 0;h = h +1;}
31
32            //Wait for quit signal from main thread
33            match rx.try_recv() {
34            Ok(_) | Err(TryRecvError::Disconnected) => {
35                println!("Timer terminated.");
36                let ticker_dur = format!("({} hour {} minute {} second)",h,m,i);
37                // Send back the time data to main thread
38                txa.send(ticker_dur).unwrap();
39                break;
40            }
41            Err(TryRecvError::Empty) => {}
42        }
43        }
44    });
45    
46    //Wait for quit signal from user
47    io::stdin().read_line(&mut String::new()).unwrap();
48    
49    //Send quit signal to timer thread
50    let _ = tx.send(());
51
52    //Receive elapsed time data
53    let received = rxa.recv().unwrap();
54
55    //Get end time
56    let end_time = chrono::Local::now().format("%-H:%M").to_string();
57
58    //Generate report
59    let ticker = format!("[{}] {} - {} {}", date,start_time, end_time,received);
60
61    //Show report
62    println!("{}",ticker);
63
64    //Copy report to clipboard
65    let mut ctx = ClipboardContext::new().unwrap();
66    ctx.set_contents(ticker.to_owned()).unwrap();

The Result #

rtimer_6OJ3oBhpFb

Benchmarking against my old Python code #

Smaller executable file, generally lower CPU and RAM usage. Cool. I'm very satisfied.

Taskmgr_bcsfhyYrrv

image


Epilogue #

In my opinon, "rewrite in rust" challenge is quite a good movement to witness it by yourself, whether Rust will actually improve your codebase or not. Go pick your old, dusty, forsaken side project that you haven't touched it since ages. Rewrite it in Rust. Do the benchmark.

Cool propaganda-styled poster that I found on Twitter. Credit : © 2022 Fission