From c80886fe7ffd4687d777b7191fc9a81968d559e2 Mon Sep 17 00:00:00 2001 From: Joshua Price Date: Wed, 30 Nov 2022 19:17:33 +0000 Subject: [PATCH 1/7] env: add devcontainer --- .devcontainer/Dockerfile | 9 +++++++++ .devcontainer/devcontainer.json | 14 ++++++++++++++ .devcontainer/setup.sh | 15 +++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100755 .devcontainer/setup.sh diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..b2802bc --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu:20.04 + +WORKDIR /home/ + +COPY . . + +RUN bash ./setup.sh + +ENV PATH="/root/.cargo/bin:$PATH" diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..a879143 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,14 @@ +{ + "name": "rust-stopwatch", + "extensions": [ + "matklad.rust-analyzer", + "bungcip.better-toml" + ], + "dockerFile": "Dockerfile", + "settings": { + "editor.formatOnSave": true, + "files.exclude": { + "**/LICENSE.txt": true + } + } +} \ No newline at end of file diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh new file mode 100755 index 0000000..a8e0ece --- /dev/null +++ b/.devcontainer/setup.sh @@ -0,0 +1,15 @@ +apt-get update +apt-get install -y \ + curl \ + git \ + gnupg2 \ + jq \ + sudo \ + build-essential \ + openssl + +curl https://sh.rustup.rs -sSf | sh -s -- -y +source "$HOME/.cargo/env" +rustup component add clippy rustfmt + +cargo build From ee88a686d9ee316f7f9cc03a13b0f3c2b26d9310 Mon Sep 17 00:00:00 2001 From: Joshua Price Date: Wed, 30 Nov 2022 19:18:14 +0000 Subject: [PATCH 2/7] feat: add rust edition to Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3bd1a72..55a2b09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] - name = "stopwatch" version = "0.0.7" +edition = "2021" authors = ["Chucky Ellison "] description = "A stopwatch library for timing things." From 6220487a8edbd7e06a7b42fa48695356f7fd744f Mon Sep 17 00:00:00 2001 From: Joshua Price Date: Wed, 30 Nov 2022 19:30:05 +0000 Subject: [PATCH 3/7] refactor: update edition to 2021 & remove unneeded crates --- Cargo.toml | 2 +- src/lib.rs | 186 ++++++++++++++++++++++++------------------------ tests/lib.rs | 196 +++++++++++++++++++++++++-------------------------- 3 files changed, 189 insertions(+), 195 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 55a2b09..9a84a0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,4 +11,4 @@ keywords = ["stopwatch", "timing"] license = "MIT" [dependencies] -num = "0.1.32" +num-traits = "0.2.15" diff --git a/src/lib.rs b/src/lib.rs index fc7fcc3..aec402f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,118 +4,114 @@ use std::time::{Duration, Instant}; #[derive(Clone, Copy)] pub struct Stopwatch { - /// The time the stopwatch was started last, if ever. - start_time: Option, - /// The time the stopwatch was split last, if ever. - split_time: Option, - /// The time elapsed while the stopwatch was running (between start() and stop()). - elapsed: Duration, + /// The time the stopwatch was started last, if ever. + start_time: Option, + /// The time the stopwatch was split last, if ever. + split_time: Option, + /// The time elapsed while the stopwatch was running (between start() and stop()). + elapsed: Duration, } impl Default for Stopwatch { - fn default() -> Stopwatch { - Stopwatch { - start_time: None, - split_time: None, - elapsed: Duration::from_secs(0), - } - } + fn default() -> Stopwatch { + Stopwatch { + start_time: None, + split_time: None, + elapsed: Duration::from_secs(0), + } + } } impl fmt::Display for Stopwatch { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - return write!(f, "{}ms", self.elapsed_ms()); - } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}ms", self.elapsed_ms()) + } } impl Stopwatch { - /// Returns a new stopwatch. - pub fn new() -> Stopwatch { - let sw: Stopwatch = Default::default(); - return sw; - } + /// Returns a new stopwatch. + pub fn new() -> Stopwatch { + let sw: Stopwatch = Default::default(); + sw + } - /// Returns a new stopwatch which will immediately be started. - pub fn start_new() -> Stopwatch { - let mut sw = Stopwatch::new(); - sw.start(); - return sw; - } + /// Returns a new stopwatch which will immediately be started. + pub fn start_new() -> Stopwatch { + let mut sw = Stopwatch::new(); + sw.start(); + sw + } - /// Starts the stopwatch. - pub fn start(&mut self) { - self.start_time = Some(Instant::now()); - } + /// Starts the stopwatch. + pub fn start(&mut self) { + self.start_time = Some(Instant::now()); + } - /// Stops the stopwatch. - pub fn stop(&mut self) { - self.elapsed = self.elapsed(); - self.start_time = None; - self.split_time = None; - } + /// Stops the stopwatch. + pub fn stop(&mut self) { + self.elapsed = self.elapsed(); + self.start_time = None; + self.split_time = None; + } - /// Resets all counters and stops the stopwatch. - pub fn reset(&mut self) { - self.elapsed = Duration::from_secs(0); - self.start_time = None; - self.split_time = None; - } + /// Resets all counters and stops the stopwatch. + pub fn reset(&mut self) { + self.elapsed = Duration::from_secs(0); + self.start_time = None; + self.split_time = None; + } - /// Resets and starts the stopwatch again. - pub fn restart(&mut self) { - self.reset(); - self.start(); - } + /// Resets and starts the stopwatch again. + pub fn restart(&mut self) { + self.reset(); + self.start(); + } - /// Returns whether the stopwatch is running. - pub fn is_running(&self) -> bool { - return self.start_time.is_some(); - } + /// Returns whether the stopwatch is running. + pub fn is_running(&self) -> bool { + self.start_time.is_some() + } - /// Returns the elapsed time since the start of the stopwatch. - pub fn elapsed(&self) -> Duration { - match self.start_time { - // stopwatch is running - Some(t1) => { - return t1.elapsed() + self.elapsed; - } - // stopwatch is not running - None => { - return self.elapsed; - } - } - } + /// Returns the elapsed time since the start of the stopwatch. + pub fn elapsed(&self) -> Duration { + match self.start_time { + // stopwatch is running + Some(t1) => t1.elapsed() + self.elapsed, + // stopwatch is not running + None => self.elapsed, + } + } - /// Returns the elapsed time since the start of the stopwatch in milliseconds. - pub fn elapsed_ms(&self) -> i64 { - let dur = self.elapsed(); - return (dur.as_secs() * 1000 + (dur.subsec_nanos() / 1000000) as u64) as i64; - } + /// Returns the elapsed time since the start of the stopwatch in milliseconds. + pub fn elapsed_ms(&self) -> i64 { + let dur = self.elapsed(); + (dur.as_secs() * 1000 + dur.subsec_millis() as u64) as i64 + } - /// Returns the elapsed time since last split or start/restart. - /// - /// If the stopwatch is in stopped state this will always return a zero Duration. - pub fn elapsed_split(&mut self) -> Duration { - match self.start_time { - // stopwatch is running - Some(start) => { - let res = match self.split_time { - Some(split) => split.elapsed(), - None => start.elapsed(), - }; - self.split_time = Some(Instant::now()); - res - } - // stopwatch is not running - None => Duration::from_secs(0), - } - } + /// Returns the elapsed time since last split or start/restart. + /// + /// If the stopwatch is in stopped state this will always return a zero Duration. + pub fn elapsed_split(&mut self) -> Duration { + match self.start_time { + // stopwatch is running + Some(start) => { + let res = match self.split_time { + Some(split) => split.elapsed(), + None => start.elapsed(), + }; + self.split_time = Some(Instant::now()); + res + } + // stopwatch is not running + None => Duration::from_secs(0), + } + } - /// Returns the elapsed time since last split or start/restart in milliseconds. - /// - /// If the stopwatch is in stopped state this will always return zero. - pub fn elapsed_split_ms(&mut self) -> i64 { - let dur = self.elapsed_split(); - return (dur.as_secs() * 1000 + (dur.subsec_nanos() / 1_000_000) as u64) as i64; - } + /// Returns the elapsed time since last split or start/restart in milliseconds. + /// + /// If the stopwatch is in stopped state this will always return zero. + pub fn elapsed_split_ms(&mut self) -> i64 { + let dur = self.elapsed_split(); + (dur.as_secs() * 1000 + dur.subsec_millis() as u64) as i64 + } } diff --git a/tests/lib.rs b/tests/lib.rs index 3a95e40..48619a7 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,172 +1,170 @@ -extern crate num; +extern crate num_traits; extern crate stopwatch; use std::time::Duration; -use stopwatch::{Stopwatch}; +use stopwatch::Stopwatch; static SLEEP_MS: i64 = 50; static TOLERANCE_PERCENTAGE: f64 = 0.3; #[test] fn repeated_stops() { - let mut sw = Stopwatch::start_new(); - for _ in 0..1000i32 { - sw.stop(); - sw.start(); - } - assert_sw_near(sw, 0); + let mut sw = Stopwatch::start_new(); + for _ in 0..1000i32 { + sw.stop(); + sw.start(); + } + assert_sw_near(sw, 0); } #[test] fn elapsed_none() { - let sw = Stopwatch::new(); - assert_eq!(sw.elapsed_ms(), 0); + let sw = Stopwatch::new(); + assert_eq!(sw.elapsed_ms(), 0); } #[test] fn elapsed_ms() { - let sw = Stopwatch::start_new(); - sleep_ms(SLEEP_MS); - assert_sw_near(sw, SLEEP_MS); + let sw = Stopwatch::start_new(); + sleep_ms(SLEEP_MS); + assert_sw_near(sw, SLEEP_MS); } #[test] fn stop() { - let mut sw = Stopwatch::start_new(); - sleep_ms(SLEEP_MS); - sw.stop(); - assert_sw_near(sw, SLEEP_MS); + let mut sw = Stopwatch::start_new(); + sleep_ms(SLEEP_MS); + sw.stop(); + assert_sw_near(sw, SLEEP_MS); - sleep_ms(SLEEP_MS); - assert_sw_near(sw, SLEEP_MS); + sleep_ms(SLEEP_MS); + assert_sw_near(sw, SLEEP_MS); } #[test] fn resume_once() { - let mut sw = Stopwatch::start_new(); - sleep_ms(SLEEP_MS); - sw.stop(); - assert_sw_near(sw, SLEEP_MS); - sw.start(); - sleep_ms(SLEEP_MS); - assert_sw_near(sw, 2 * SLEEP_MS); + let mut sw = Stopwatch::start_new(); + sleep_ms(SLEEP_MS); + sw.stop(); + assert_sw_near(sw, SLEEP_MS); + sw.start(); + sleep_ms(SLEEP_MS); + assert_sw_near(sw, 2 * SLEEP_MS); } #[test] fn resume_twice() { - let mut sw = Stopwatch::start_new(); - sleep_ms(SLEEP_MS); - sw.stop(); - assert_sw_near(sw, SLEEP_MS); - sw.start(); - sleep_ms(SLEEP_MS); - sw.stop(); - assert_sw_near(sw, 2 * SLEEP_MS); - sw.start(); - sleep_ms(SLEEP_MS); - assert_sw_near(sw, 3 * SLEEP_MS); + let mut sw = Stopwatch::start_new(); + sleep_ms(SLEEP_MS); + sw.stop(); + assert_sw_near(sw, SLEEP_MS); + sw.start(); + sleep_ms(SLEEP_MS); + sw.stop(); + assert_sw_near(sw, 2 * SLEEP_MS); + sw.start(); + sleep_ms(SLEEP_MS); + assert_sw_near(sw, 3 * SLEEP_MS); } #[test] fn is_running() { - let mut sw = Stopwatch::new(); - assert!(!sw.is_running()); - sw.start(); - assert!(sw.is_running()); - sw.stop(); - assert!(!sw.is_running()); + let mut sw = Stopwatch::new(); + assert!(!sw.is_running()); + sw.start(); + assert!(sw.is_running()); + sw.stop(); + assert!(!sw.is_running()); } #[test] fn restart() { - let mut sw = Stopwatch::start_new(); - sleep_ms(SLEEP_MS); - sw.restart(); - sleep_ms(SLEEP_MS); - assert_sw_near(sw, SLEEP_MS); + let mut sw = Stopwatch::start_new(); + sleep_ms(SLEEP_MS); + sw.restart(); + sleep_ms(SLEEP_MS); + assert_sw_near(sw, SLEEP_MS); } #[test] fn reset() { - let mut sw = Stopwatch::start_new(); - sleep_ms(SLEEP_MS); - sw.reset(); - assert!(!sw.is_running()); - assert_eq!(sw.elapsed_ms(), 0); + let mut sw = Stopwatch::start_new(); + sleep_ms(SLEEP_MS); + sw.reset(); + assert!(!sw.is_running()); + assert_eq!(sw.elapsed_ms(), 0); } #[test] fn split_on_started_watch() { - let mut sw = Stopwatch::start_new(); - sleep_ms(SLEEP_MS); - assert_split_near(&mut sw, SLEEP_MS); - sleep_ms(SLEEP_MS); - assert_split_near(&mut sw, SLEEP_MS); + let mut sw = Stopwatch::start_new(); + sleep_ms(SLEEP_MS); + assert_split_near(&mut sw, SLEEP_MS); + sleep_ms(SLEEP_MS); + assert_split_near(&mut sw, SLEEP_MS); - assert_sw_near(sw, 2 * SLEEP_MS); + assert_sw_near(sw, 2 * SLEEP_MS); } #[test] fn split_on_resumed_watch() { - let mut sw = Stopwatch::new(); - sleep_ms(SLEEP_MS); - assert_split_near(&mut sw, 0); - sleep_ms(SLEEP_MS); - assert_split_near(&mut sw, 0); - sw.start(); - sleep_ms(SLEEP_MS); - assert_split_near(&mut sw, SLEEP_MS); - sleep_ms(SLEEP_MS); - assert_split_near(&mut sw, SLEEP_MS); - sw.stop(); - sleep_ms(SLEEP_MS); - assert_split_near(&mut sw, 0); - - assert_sw_near(sw, 2 * SLEEP_MS); + let mut sw = Stopwatch::new(); + sleep_ms(SLEEP_MS); + assert_split_near(&mut sw, 0); + sleep_ms(SLEEP_MS); + assert_split_near(&mut sw, 0); + sw.start(); + sleep_ms(SLEEP_MS); + assert_split_near(&mut sw, SLEEP_MS); + sleep_ms(SLEEP_MS); + assert_split_near(&mut sw, SLEEP_MS); + sw.stop(); + sleep_ms(SLEEP_MS); + assert_split_near(&mut sw, 0); + + assert_sw_near(sw, 2 * SLEEP_MS); } #[test] fn split_after_reset() { - let mut sw = Stopwatch::start_new(); - sleep_ms(SLEEP_MS); - assert_split_near(&mut sw, SLEEP_MS); - sw.reset(); - sleep_ms(SLEEP_MS); - assert_split_near(&mut sw, 0); + let mut sw = Stopwatch::start_new(); + sleep_ms(SLEEP_MS); + assert_split_near(&mut sw, SLEEP_MS); + sw.reset(); + sleep_ms(SLEEP_MS); + assert_split_near(&mut sw, 0); } #[test] fn split_after_restart() { - let mut sw = Stopwatch::start_new(); - sleep_ms(SLEEP_MS); - assert_split_near(&mut sw, SLEEP_MS); - sw.restart(); - sleep_ms(SLEEP_MS); - assert_split_near(&mut sw, SLEEP_MS); + let mut sw = Stopwatch::start_new(); + sleep_ms(SLEEP_MS); + assert_split_near(&mut sw, SLEEP_MS); + sw.restart(); + sleep_ms(SLEEP_MS); + assert_split_near(&mut sw, SLEEP_MS); } - - /////////////// helpers fn sleep_ms(ms: i64) { - use num::ToPrimitive; - std::thread::sleep(Duration::from_millis(ms.to_u64().unwrap())) + use num_traits::ToPrimitive; + std::thread::sleep(Duration::from_millis(ms.to_u64().unwrap())) } fn assert_near(x: i64, y: i64, tolerance: i64) { - let diff = (x - y).abs(); - if diff > tolerance { - panic!("Expected {:?}, got {:?}", x, y); - } + let diff = (x - y).abs(); + if diff > tolerance { + panic!("Expected {:?}, got {:?}", x, y); + } } fn assert_sw_near(sw: Stopwatch, elapsed: i64) { - let tolerance_value = (TOLERANCE_PERCENTAGE * elapsed as f64) as i64; - assert_near(elapsed, sw.elapsed_ms(), tolerance_value); + let tolerance_value = (TOLERANCE_PERCENTAGE * elapsed as f64) as i64; + assert_near(elapsed, sw.elapsed_ms(), tolerance_value); } fn assert_split_near(sw: &mut Stopwatch, elapsed: i64) { - let tolerance_value = (TOLERANCE_PERCENTAGE * elapsed as f64) as i64; - assert_near(elapsed, sw.elapsed_split_ms(), tolerance_value); -} \ No newline at end of file + let tolerance_value = (TOLERANCE_PERCENTAGE * elapsed as f64) as i64; + assert_near(elapsed, sw.elapsed_split_ms(), tolerance_value); +} From f39fd4512df78cae54eef70de0987aa54f8872a8 Mon Sep 17 00:00:00 2001 From: Joshua Price Date: Thu, 1 Dec 2022 14:46:30 +0000 Subject: [PATCH 4/7] refactor: simplify constructor --- src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index aec402f..7da6e5b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,8 +31,7 @@ impl fmt::Display for Stopwatch { impl Stopwatch { /// Returns a new stopwatch. pub fn new() -> Stopwatch { - let sw: Stopwatch = Default::default(); - sw + Stopwatch::default() } /// Returns a new stopwatch which will immediately be started. From 937cc3fa4e305474387d08c03e056c6e5a7693a0 Mon Sep 17 00:00:00 2001 From: Joshua Price Date: Thu, 1 Dec 2022 14:50:12 +0000 Subject: [PATCH 5/7] refactor: remove unneeded extern crates --- tests/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/lib.rs b/tests/lib.rs index 48619a7..0ef8869 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,6 +1,3 @@ -extern crate num_traits; -extern crate stopwatch; - use std::time::Duration; use stopwatch::Stopwatch; From 936fe282b95d6b8d8d69d2219bc5ab5c5dbcab33 Mon Sep 17 00:00:00 2001 From: Joshua Price Date: Thu, 1 Dec 2022 15:16:26 +0000 Subject: [PATCH 6/7] env: set vscode as git editor --- .devcontainer/devcontainer.json | 4 ++++ .devcontainer/setup.sh | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index a879143..bb121aa 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,6 +5,10 @@ "bungcip.better-toml" ], "dockerFile": "Dockerfile", + "containerEnv": { + "GIT_EDITOR": "code --wait" + }, + "onCreateCommand": "cargo build", "settings": { "editor.formatOnSave": true, "files.exclude": { diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh index a8e0ece..3d9a06e 100755 --- a/.devcontainer/setup.sh +++ b/.devcontainer/setup.sh @@ -11,5 +11,3 @@ apt-get install -y \ curl https://sh.rustup.rs -sSf | sh -s -- -y source "$HOME/.cargo/env" rustup component add clippy rustfmt - -cargo build From dd9adfef0ed86ef41091dc9104c0aaf927dbee8e Mon Sep 17 00:00:00 2001 From: Joshua Price Date: Thu, 1 Dec 2022 15:21:58 +0000 Subject: [PATCH 7/7] refactor: add explicit returns --- src/lib.rs | 12 ++++++------ tests/lib.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7da6e5b..821c50b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,21 +24,21 @@ impl Default for Stopwatch { impl fmt::Display for Stopwatch { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}ms", self.elapsed_ms()) + return write!(f, "{}ms", self.elapsed_ms()); } } impl Stopwatch { /// Returns a new stopwatch. pub fn new() -> Stopwatch { - Stopwatch::default() + return Stopwatch::default(); } /// Returns a new stopwatch which will immediately be started. pub fn start_new() -> Stopwatch { let mut sw = Stopwatch::new(); sw.start(); - sw + return sw; } /// Starts the stopwatch. @@ -84,7 +84,7 @@ impl Stopwatch { /// Returns the elapsed time since the start of the stopwatch in milliseconds. pub fn elapsed_ms(&self) -> i64 { let dur = self.elapsed(); - (dur.as_secs() * 1000 + dur.subsec_millis() as u64) as i64 + return (dur.as_secs() * 1000 + dur.subsec_millis() as u64) as i64; } /// Returns the elapsed time since last split or start/restart. @@ -99,7 +99,7 @@ impl Stopwatch { None => start.elapsed(), }; self.split_time = Some(Instant::now()); - res + return res; } // stopwatch is not running None => Duration::from_secs(0), @@ -111,6 +111,6 @@ impl Stopwatch { /// If the stopwatch is in stopped state this will always return zero. pub fn elapsed_split_ms(&mut self) -> i64 { let dur = self.elapsed_split(); - (dur.as_secs() * 1000 + dur.subsec_millis() as u64) as i64 + return (dur.as_secs() * 1000 + dur.subsec_millis() as u64) as i64; } } diff --git a/tests/lib.rs b/tests/lib.rs index 0ef8869..292c38b 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -146,7 +146,7 @@ fn split_after_restart() { fn sleep_ms(ms: i64) { use num_traits::ToPrimitive; - std::thread::sleep(Duration::from_millis(ms.to_u64().unwrap())) + return std::thread::sleep(Duration::from_millis(ms.to_u64().unwrap())); } fn assert_near(x: i64, y: i64, tolerance: i64) {