fret_ui_kit/primitives/
progress.rs1pub fn normalize_progress(value: f32, min: f32, max: f32) -> f32 {
11 if !value.is_finite() || !min.is_finite() || !max.is_finite() {
12 return 0.0;
13 }
14 let span = max - min;
15 if !span.is_finite() || span.abs() <= f32::EPSILON {
16 return 0.0;
17 }
18 ((value - min) / span).clamp(0.0, 1.0)
19}
20
21pub fn normalize_progress_opt(value: Option<f32>, min: f32, max: f32) -> Option<f32> {
23 value.map(|v| normalize_progress(v, min, max))
24}
25
26#[cfg(test)]
27mod tests {
28 use super::*;
29
30 #[test]
31 fn normalize_progress_clamps_to_unit_interval() {
32 assert_eq!(normalize_progress(-1.0, 0.0, 10.0), 0.0);
33 assert_eq!(normalize_progress(0.0, 0.0, 10.0), 0.0);
34 assert_eq!(normalize_progress(5.0, 0.0, 10.0), 0.5);
35 assert_eq!(normalize_progress(10.0, 0.0, 10.0), 1.0);
36 assert_eq!(normalize_progress(999.0, 0.0, 10.0), 1.0);
37 }
38
39 #[test]
40 fn normalize_progress_handles_degenerate_ranges() {
41 assert_eq!(normalize_progress(5.0, 0.0, 0.0), 0.0);
42 assert_eq!(normalize_progress(f32::NAN, 0.0, 1.0), 0.0);
43 }
44
45 #[test]
46 fn normalize_progress_opt_preserves_none() {
47 assert_eq!(normalize_progress_opt(None, 0.0, 10.0), None);
48 assert_eq!(normalize_progress_opt(Some(5.0), 0.0, 10.0), Some(0.5));
49 }
50}