clock_timer/lib.rs
1//! # Rust Time Utility Library
2//!
3//! This library provides two main utilities for time management:
4//! a `TimerStruct` for countdown timers and a `StopwatchStruct` for measuring elapsed time.
5
6
7/// Module for countdown timer functionalities.
8pub mod timer {
9 use std::{io::Write, thread, time::Duration};
10
11 /// Represents a countdown timer.
12 #[derive(Clone, Copy, Debug)]
13 pub struct TimerStruct {
14 /// The total duration of the timer in seconds.
15 pub duration: u32,
16 /// The initial hours component of the timer.
17 pub hours: u32,
18 /// The initial minutes component of the timer.
19 pub minutes: u32,
20 /// The initial seconds component of the timer.
21 pub seconds: u32,
22 }
23
24 impl TimerStruct {
25 /// Creates a new `TimerStruct` instance.
26 ///
27 /// # Arguments
28 ///
29 /// * `hours` - The hours component of the timer duration.
30 /// * `minutes` - The minutes component of the timer duration.
31 /// * `seconds` - The seconds component of the timer duration.
32 ///
33 /// # Returns
34 ///
35 /// * `Ok(TimerStruct)` if the total duration calculated from `hours`, `minutes`,
36 /// and `seconds` is greater than 0.
37 /// * `Err("Duration need to be 1 or more seconds.")` if the total duration is 0.
38 ///
39 /// # Examples
40 ///
41 /// ```
42 /// use your_crate_name::TimerStruct; // Replace your_crate_name with your actual crate name
43 ///
44 /// let timer = TimerStruct::new(0, 1, 30).expect("Failed to create timer"); // 1 minute 30 seconds
45 /// let invalid_timer = TimerStruct::new(0, 0, 0); // This will return an Err
46 /// ```
47 pub fn new(hours: u32, minutes: u32, seconds: u32) -> Result<TimerStruct, &'static str> {
48 let duration = (hours * 3600) + (minutes * 60) + seconds;
49
50 if duration == 0 {
51 return Err("Duration need to be 1 or more seconds.");
52 }
53
54 Ok(TimerStruct {
55 duration,
56 hours,
57 minutes,
58 seconds,
59 })
60 }
61
62 /// Starts the countdown timer.
63 ///
64 /// The timer will print the remaining time to the provided writer every second,
65 /// overwriting the previous line. When the timer reaches 0, it prints the final
66 /// `0:0:0` with a newline and stops.
67 ///
68 /// # Arguments
69 ///
70 /// * `writer` - A mutable reference to any type that implements the `std::io::Write`
71 /// trait (e.g., `&mut std::io::Stdout`).
72 ///
73 /// # Examples
74 ///
75 /// ```
76 /// use your_crate_name::TimerStruct; // Replace your_crate_name with your actual crate name
77 /// use std::io::{self, stdout};
78 ///
79 /// let timer = TimerStruct::new(0, 0, 5).unwrap(); // 5-second timer
80 /// let mut writer = stdout();
81 /// timer.start_timer(&mut writer);
82 /// println!("Timer finished!");
83 /// ```
84 pub fn start_timer<W: Write>(&self, writer: &mut W) {
85 let mut current_duration = self.duration;
86 let one_second = Duration::from_secs(1);
87
88 loop {
89 // Calculate display components from the current total duration
90 let display_hours = current_duration / 3600;
91 let remaining_seconds_after_hours = current_duration % 3600;
92 let display_minutes = remaining_seconds_after_hours / 60;
93 let display_seconds = remaining_seconds_after_hours % 60;
94
95 let time_display_string =
96 format!("{}:{}:{}", display_hours, display_minutes, display_seconds);
97
98 if current_duration == 0 {
99 // If duration is 0, this is the final display. Print with a newline and break.
100 writeln!(writer, "{}", time_display_string).unwrap();
101 break;
102 } else {
103 // For all other durations, print with a carriage return to overwrite the line.
104 write!(writer, "{}\r", time_display_string).unwrap();
105 writer.flush().unwrap(); // Ensure the output is flushed immediately
106 }
107
108 thread::sleep(one_second);
109 current_duration -= 1;
110 }
111 }
112 }
113}
114
115/// Re-exports `TimerStruct` from the `timer` module for easier access.
116pub use timer::TimerStruct;
117
118/// Module for stopwatch functionalities.
119pub mod stopwatch {
120 use std::{io::Write,thread, time::Duration};
121
122 /// Represents the current status of the stopwatch.
123 #[derive(Clone, Debug)]
124 pub enum StopwatchStatus {
125 /// The stopwatch is currently stopped.
126 Stopped,
127 /// The stopwatch is currently running.
128 Running,
129 }
130
131 /// Represents a stopwatch that measures elapsed time.
132 ///
133 /// It takes a generic type `T` which must be a closure that accepts a `u32`
134 /// (the final `current_time` when the stopwatch stops).
135 #[derive(Debug, Clone)]
136 pub struct StopwatchStruct<T>
137 where T: Fn(u32),
138 {
139 /// The current elapsed time in seconds.
140 pub current_time: u32,
141 /// The current status of the stopwatch (Running or Stopped).
142 pub status: StopwatchStatus,
143 /// A closure that will be executed when the stopwatch is stopped.
144 /// It receives the final `current_time` as an argument.
145 pub operation_on_stop: T,
146 }
147
148 impl<T> StopwatchStruct<T>
149 where T: Fn(u32),
150 {
151 /// Creates a new `StopwatchStruct` instance.
152 ///
153 /// # Arguments
154 ///
155 /// * `operation_on_stop` - A closure that will be called when the stopwatch status
156 /// is set to `Stopped`. It receives the total elapsed time in seconds as its argument.
157 ///
158 /// # Returns
159 ///
160 /// A new `StopwatchStruct` initialized with `current_time` at 0 and `status` as `Running`.
161 ///
162 /// # Examples
163 ///
164 /// ```
165 /// use your_crate_name::stopwatch::{StopwatchStruct, StopwatchStatus}; // Replace your_crate_name
166 ///
167 /// let mut stopwatch = StopwatchStruct::new(|time| {
168 /// println!("Stopwatch stopped at {} seconds.", time);
169 /// });
170 /// ```
171 pub fn new(operation_on_stop: T) -> StopwatchStruct<T> {
172 StopwatchStruct {
173 current_time: 0,
174 status: StopwatchStatus::Running,
175 operation_on_stop,
176 }
177 }
178
179 /// Starts the stopwatch.
180 ///
181 /// The stopwatch will increment its `current_time` every second and print the elapsed time
182 /// to the provided writer, overwriting the previous line. The loop continues indefinitely
183 /// until the `status` field of the `StopwatchStruct` is manually set to `StopwatchStatus::Stopped`
184 /// from outside this function (e.g., from another thread or an external signal).
185 ///
186 /// # Arguments
187 ///
188 /// * `writer` - A mutable reference to any type that implements the `std::io::Write`
189 /// trait (e.g., `&mut std::io::Stdout`).
190 ///
191 /// # Examples
192 ///
193 /// ```
194 /// use your_crate_name::stopwatch::{StopwatchStruct, StopwatchStatus}; // Replace your_crate_name
195 /// use std::{io::stdout, thread, time::Duration};
196 ///
197 /// let mut stopwatch = StopwatchStruct::new(|time| {
198 /// println!("\nStopwatch finished at {} seconds!", time);
199 /// });
200 ///
201 /// let mut writer = stdout();
202 ///
203 /// // To stop the stopwatch, you would typically change its status from another thread
204 /// // or based on some external event. For demonstration, we'll do it after a delay.
205 /// let mut stopwatch_clone = stopwatch.clone(); // Clone to move into another thread
206 /// thread::spawn(move || {
207 /// thread::sleep(Duration::from_secs(5));
208 /// stopwatch_clone.status = StopwatchStatus::Stopped; // Stop after 5 seconds
209 /// });
210 ///
211 /// stopwatch.start_timer(&mut writer);
212 /// println!("Stopwatch loop ended.");
213 /// ```
214 pub fn start_timer<W: Write>(&mut self, writer: &mut W) {
215 loop {
216 match self.status {
217 StopwatchStatus::Stopped => {
218 (self.operation_on_stop)(self.current_time);
219 break;
220 },
221 StopwatchStatus::Running => (),
222 }
223
224 let hours = self.current_time / 3600;
225 let mut remaining = self.current_time % 3600;
226 let minutes = remaining / 60;
227 remaining %= 60;
228
229 let output_format = format!("{}:{}:{}", hours, minutes, remaining);
230
231 if self.current_time == 0 {
232 write!(writer, "{}", output_format).unwrap();
233 }
234
235 thread::sleep(Duration::from_secs(1));
236
237 self.current_time += 1;
238
239 write!(writer, "{}\r", output_format).unwrap();
240
241 writer.flush().unwrap();
242 }
243 }
244
245 pub fn stop_timer(seconds: u32, reference: &mut StopwatchStruct<T>)
246 where T: Fn(u32),
247 {
248 let duration = Duration::from_secs(seconds.into());
249 thread::sleep(duration);
250 reference.status = StopwatchStatus::Stopped;
251 }
252 }
253}