Duration to String enhanced with tests

Adds checks for if a bit in a u8 is set or clear
This commit is contained in:
Trevor Merritt 2025-07-23 11:19:22 -04:00
parent 3280123d22
commit 6d51a4d3a6
7 changed files with 133 additions and 42 deletions

View File

@ -1,36 +0,0 @@
use std::time::Duration;
pub fn duration_to_string(to_convert: Duration) -> String {
let mut total_seconds = to_convert.as_secs() as u32;
let mut working_string = String::new();
if total_seconds > 86400 {
// days
let num_days = (total_seconds / SECONDS_IN_DAY) as u32;
working_string = format!("{} days", num_days);
total_seconds = total_seconds - (num_days * SECONDS_IN_DAY);
}
if total_seconds > 3600 {
// hours
let num_hours = (total_seconds / SECONDS_IN_HOUR) as u32;
if num_hours > 0 {
working_string = format!("{} {} hours", working_string, num_hours);
total_seconds = total_seconds - (num_hours * SECONDS_IN_HOUR);
}
}
if total_seconds > 60 {
let num_minutes = (total_seconds / SECONDS_IN_MINUTE) as u32;
if num_minutes > 0 {
working_string = format!("{} {} minutes", working_string, num_minutes);
total_seconds = total_seconds - (num_minutes * SECONDS_IN_MINUTE);
}
// minutes
}
working_string = format!("{} {} seconds", working_string, total_seconds);
working_string
}

View File

@ -0,0 +1,38 @@
use std::time::Duration;
pub const SECONDS_IN_MINUTE: u32 = 60;
pub const SECONDS_IN_HOUR: u32 = SECONDS_IN_MINUTE * 60;
pub const SECONDS_IN_DAY: u32 = SECONDS_IN_HOUR * 24;
pub fn duration_to_string(to_convert: Duration, show_zeros: Option<bool>) -> String {
const SECONDS_IN_DAY: u32 = 86400;
const SECONDS_IN_HOUR: u32 = 3600;
const SECONDS_IN_MINUTE: u32 = 60;
let should_show_zero = show_zeros.unwrap_or(false);
let mut total_seconds = to_convert.as_secs() as u32;
let mut parts = Vec::new();
let units = [
(SECONDS_IN_DAY, "day"),
(SECONDS_IN_HOUR, "hour"),
(SECONDS_IN_MINUTE, "minute"),
(1, "second"),
];
for &(unit_seconds, unit_name) in &units {
let count = total_seconds / unit_seconds;
total_seconds %= unit_seconds;
if count > 0 || should_show_zero {
let label = if count == 1 {
unit_name.to_string()
} else {
format!("{}s", unit_name)
};
parts.push(format!("{} {}", count, label));
}
}
parts.join(" ")
}

View File

@ -0,0 +1,2 @@
pub mod duration_to_string;
mod tests;

View File

@ -0,0 +1,43 @@
use std::time::Duration;
use crate::duration_to_string::duration_to_string::duration_to_string;
#[cfg(test)]
mod test {
use super::*;
use crate::duration_to_string::duration_to_string::*;
#[test]
fn multi_duration_to_string() {
let params: Vec<(&str, Duration, Option<bool>)> = vec![
("1 second", Duration::from_secs(1), Some(false)),
("4 seconds", Duration::from_secs(4), Some(false)),
("1 minute", Duration::from_secs(SECONDS_IN_MINUTE as u64), Some(false)),
("4 minutes", Duration::from_secs((SECONDS_IN_MINUTE * 4) as u64), Some(false)),
("1 hour", Duration::from_secs(SECONDS_IN_HOUR as u64), Some(false)),
("4 hours", Duration::from_secs((SECONDS_IN_HOUR * 4) as u64), Some(false)),
("4 hours 5 minutes", Duration::from_secs((SECONDS_IN_HOUR * 4 + SECONDS_IN_MINUTE * 5) as u64), Some(false)),
("1 day", Duration::from_secs(SECONDS_IN_DAY as u64), Some(false)),
("0 days 0 hours 0 minutes 1 second", Duration::from_secs(1), Some(true)),
("0 days 0 hours 0 minutes 4 seconds", Duration::from_secs(4), Some(true)),
("0 days 0 hours 1 minute 0 seconds", Duration::from_secs(SECONDS_IN_MINUTE as u64), Some(true)),
("0 days 0 hours 4 minutes 0 seconds", Duration::from_secs((SECONDS_IN_MINUTE * 4) as u64), Some(true)),
("0 days 1 hour 0 minutes 0 seconds", Duration::from_secs(SECONDS_IN_HOUR as u64), Some(true)),
("0 days 4 hours 0 minutes 0 seconds", Duration::from_secs((SECONDS_IN_HOUR * 4) as u64), Some(true)),
("0 days 4 hours 5 minutes 0 seconds", Duration::from_secs((SECONDS_IN_HOUR * 4 + SECONDS_IN_MINUTE * 5) as u64), Some(true)),
("1 day 0 hours 0 minutes 0 seconds", Duration::from_secs(SECONDS_IN_DAY as u64), Some(true)),
("1 day 0 hours 0 minutes 1 second", Duration::from_secs((SECONDS_IN_DAY + 1) as u64), Some(true)),
("1 second", Duration::from_secs(1), None),
("4 seconds", Duration::from_secs(4), None),
("1 minute", Duration::from_secs(SECONDS_IN_MINUTE as u64), None),
("4 minutes", Duration::from_secs((SECONDS_IN_MINUTE * 4) as u64), None),
("1 hour", Duration::from_secs(SECONDS_IN_HOUR as u64), None),
("4 hours", Duration::from_secs((SECONDS_IN_HOUR * 4) as u64), None),
("4 hours 5 minutes", Duration::from_secs((SECONDS_IN_HOUR * 4 + SECONDS_IN_MINUTE * 5) as u64), None),
("1 day", Duration::from_secs(SECONDS_IN_DAY as u64), None),
];
for (expected, actual, show) in params {
assert_eq!(expected, duration_to_string(actual, show));
}
}
}

View File

@ -8,12 +8,12 @@ impl NumberSystemConversion {
/// ex: 0xff -> true, true, true, true, true, true, true, true
/// 0xa0 -> true, false, true, false, false, false, false, false
pub fn byte_to_bool(from: u8) -> [bool; 8] {
let mut return_values = [false; 8];
let mut result = [false; 8];
for i in 0..8 {
let new_value = from >> i & 0x1 == 1;
return_values[i as usize] = new_value;
// Extract the i-th bit and convert it to a boolean
result[i] = ((from >> i) & 1) != 0;
}
return_values
result
}
/// bool_to_byte
@ -114,4 +114,19 @@ impl NumberSystemConversion {
pub fn clear_low_bits(to_clear: u16) -> u16 {
to_clear & 0xff00
}
/// is_bit_set
///
/// Checks if a specified bit is set
pub fn is_bit_set(to_check: u8, bit_to_check: u8) -> bool {
(to_check >> bit_to_check) & 0x01 == 1
}
/// is_bit_clear
///
/// Checks if a specified bit is clear
/// LSB = 0 MSB = 7
pub fn is_bit_clear(to_check: u8, bit_to_check: u8) -> bool {
(to_check >> bit_to_check) & 0x01 != 1
}
}

View File

@ -8,7 +8,6 @@ fn read_bin(source: &str) -> Vec<u8> {
fn read_display(source: &str) -> String {
let full_path = format!("/home/tmerritt/Projects/trevors_utilities/resources/data_to_text/{}.display", source);
// println!("FULL PATH DIS: [{}]", full_path);
std::fs::read_to_string(full_path).unwrap()
}

View File

@ -147,4 +147,34 @@ fn clear_low_bits() {
NumberSystemConversion::clear_low_bits(src),
dst);
}
}
}
#[test]
fn is_bit_set_checks() {
let params = vec![
(0b0000_0001, vec![true, false, false, false, false, false, false, false]),
(0b1111_1111, vec![true, true, true, true, true, true, true, true]),
(0b1010_1010, vec![false, true, false, true, false, true, false, true])
];
for (base, options) in params {
for (index, expected) in options.iter().enumerate() {
assert_eq!(*expected, NumberSystemConversion::is_bit_set(base, index as u8));
}
}
}
#[test]
fn is_bit_clear_checks() {
let params = vec![
(0b0000_0001, vec![false, true, true, true, true, true, true, true]),
(0b1111_1111, vec![false, false, false, false, false, false, false, false]),
(0b1010_1010, vec![true, false, true, false, true, false, true, false])
];
for (base, options) in params {
for (index, expected) in options.iter().enumerate() {
assert_eq!(*expected, NumberSystemConversion::is_bit_clear(base, index as u8));
}
}
}