Skip to main content

oxihuman_core/
resource_tracker.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5pub struct ResourceTracker {
6    pub allocated: u64,
7    pub limit: u64,
8    pub peak: u64,
9}
10
11impl ResourceTracker {
12    pub fn new(limit: u64) -> Self {
13        ResourceTracker {
14            allocated: 0,
15            limit,
16            peak: 0,
17        }
18    }
19}
20
21pub fn new_resource_tracker(limit: u64) -> ResourceTracker {
22    ResourceTracker::new(limit)
23}
24
25pub fn tracker_allocate(t: &mut ResourceTracker, amount: u64) -> bool {
26    if t.allocated + amount > t.limit {
27        return false;
28    }
29    t.allocated += amount;
30    if t.allocated > t.peak {
31        t.peak = t.allocated;
32    }
33    true
34}
35
36pub fn tracker_free(t: &mut ResourceTracker, amount: u64) {
37    t.allocated = t.allocated.saturating_sub(amount);
38}
39
40pub fn tracker_available(t: &ResourceTracker) -> u64 {
41    t.limit.saturating_sub(t.allocated)
42}
43
44pub fn tracker_peak(t: &ResourceTracker) -> u64 {
45    t.peak
46}
47
48pub fn tracker_utilization(t: &ResourceTracker) -> f32 {
49    if t.limit == 0 {
50        return 0.0;
51    }
52    t.allocated as f32 / t.limit as f32
53}
54
55pub fn tracker_is_full(t: &ResourceTracker) -> bool {
56    t.allocated >= t.limit
57}
58
59pub fn tracker_reset(t: &mut ResourceTracker) {
60    t.allocated = 0;
61    t.peak = 0;
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn test_new() {
70        /* new tracker starts empty */
71        let t = new_resource_tracker(100);
72        assert_eq!(tracker_available(&t), 100);
73        assert_eq!(t.allocated, 0);
74    }
75
76    #[test]
77    fn test_allocate_success() {
78        /* allocate within limit succeeds */
79        let mut t = new_resource_tracker(100);
80        assert!(tracker_allocate(&mut t, 50));
81        assert_eq!(t.allocated, 50);
82    }
83
84    #[test]
85    fn test_allocate_over_limit() {
86        /* allocate beyond limit fails */
87        let mut t = new_resource_tracker(100);
88        assert!(!tracker_allocate(&mut t, 101));
89        assert_eq!(t.allocated, 0);
90    }
91
92    #[test]
93    fn test_free() {
94        /* free reduces allocation */
95        let mut t = new_resource_tracker(100);
96        tracker_allocate(&mut t, 60);
97        tracker_free(&mut t, 20);
98        assert_eq!(t.allocated, 40);
99    }
100
101    #[test]
102    fn test_peak() {
103        /* peak tracks highest allocation */
104        let mut t = new_resource_tracker(200);
105        tracker_allocate(&mut t, 100);
106        tracker_free(&mut t, 50);
107        assert_eq!(tracker_peak(&t), 100);
108    }
109
110    #[test]
111    fn test_utilization() {
112        /* utilization is ratio of allocated to limit */
113        let mut t = new_resource_tracker(200);
114        tracker_allocate(&mut t, 100);
115        assert!((tracker_utilization(&t) - 0.5).abs() < 1e-6);
116    }
117
118    #[test]
119    fn test_is_full() {
120        /* is_full when at limit */
121        let mut t = new_resource_tracker(50);
122        tracker_allocate(&mut t, 50);
123        assert!(tracker_is_full(&t));
124    }
125
126    #[test]
127    fn test_reset() {
128        /* reset clears allocated and peak */
129        let mut t = new_resource_tracker(100);
130        tracker_allocate(&mut t, 80);
131        tracker_reset(&mut t);
132        assert_eq!(t.allocated, 0);
133        assert_eq!(t.peak, 0);
134    }
135}