1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub enum FitVerdict {
7 RunsWell,
9 TightFit,
11 TooLarge,
13}
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17pub struct FitAssessment {
18 pub verdict: FitVerdict,
20 pub required_bytes: i64,
22}
23
24impl FitVerdict {
25 const MEMORY_OVERHEAD_FACTOR: f64 = 1.25;
27 const RUNS_WELL_FRACTION: f64 = 0.75;
29 const TIGHT_FIT_FRACTION: f64 = 0.95;
31
32 pub fn assess(footprint_mb: Option<i64>, total_memory_bytes: u64) -> Option<FitAssessment> {
35 let footprint_mb = footprint_mb.filter(|&mb| mb > 0)?;
36 if total_memory_bytes == 0 {
37 return None;
38 }
39 let required_bytes =
40 (footprint_mb as f64 * (1i64 << 20) as f64 * Self::MEMORY_OVERHEAD_FACTOR) as i64;
41 let share = required_bytes as f64 / total_memory_bytes as f64;
42 let verdict = if share < Self::RUNS_WELL_FRACTION {
43 FitVerdict::RunsWell
44 } else if share < Self::TIGHT_FIT_FRACTION {
45 FitVerdict::TightFit
46 } else {
47 FitVerdict::TooLarge
48 };
49 Some(FitAssessment {
50 verdict,
51 required_bytes,
52 })
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 const GIB: u64 = 1 << 30;
61
62 #[test]
63 fn an_unknown_or_empty_footprint_is_unassessable() {
64 assert!(FitVerdict::assess(None, 16 * GIB).is_none());
65 assert!(FitVerdict::assess(Some(0), 16 * GIB).is_none());
66 assert!(FitVerdict::assess(Some(-5), 16 * GIB).is_none());
67 assert!(FitVerdict::assess(Some(1000), 0).is_none());
68 }
69
70 #[test]
71 fn the_verdict_tracks_the_memory_share() {
72 let assessment = FitVerdict::assess(Some(1024), 16 * GIB).unwrap();
74 assert_eq!(assessment.verdict, FitVerdict::RunsWell);
75
76 let tight = FitVerdict::assess(Some(12 * 1024), 16 * GIB).unwrap();
78 assert_eq!(tight.verdict, FitVerdict::TightFit);
79
80 let too_large = FitVerdict::assess(Some(16 * 1024), 16 * GIB).unwrap();
82 assert_eq!(too_large.verdict, FitVerdict::TooLarge);
83 }
84
85 #[test]
86 fn required_bytes_includes_the_overhead_factor() {
87 let assessment = FitVerdict::assess(Some(1024), 64 * GIB).unwrap();
88 assert_eq!(assessment.required_bytes, 1280 * (1 << 20));
90 }
91}