just_engine/runner/ds/
heap.rs1use crate::runner::ds::error::JErrorType;
6
7#[derive(Debug, Clone)]
9pub struct HeapConfig {
10 pub max_bytes: Option<usize>,
12}
13
14impl HeapConfig {
15 pub fn unlimited() -> Self {
17 HeapConfig { max_bytes: None }
18 }
19
20 pub fn with_limit(max_bytes: usize) -> Self {
22 HeapConfig {
23 max_bytes: Some(max_bytes),
24 }
25 }
26}
27
28impl Default for HeapConfig {
29 fn default() -> Self {
30 Self::unlimited()
31 }
32}
33
34#[derive(Debug)]
36pub struct Heap {
37 config: HeapConfig,
38 allocated_bytes: usize,
39}
40
41impl Heap {
42 pub fn new(config: HeapConfig) -> Self {
44 Heap {
45 config,
46 allocated_bytes: 0,
47 }
48 }
49
50 pub fn allocate(&mut self, bytes: usize) -> Result<(), JErrorType> {
54 if let Some(max_bytes) = self.config.max_bytes {
55 if self.allocated_bytes + bytes > max_bytes {
56 return Err(JErrorType::RangeError("Out of memory".to_string()));
57 }
58 }
59 self.allocated_bytes += bytes;
60 Ok(())
61 }
62
63 pub fn deallocate(&mut self, bytes: usize) {
65 self.allocated_bytes = self.allocated_bytes.saturating_sub(bytes);
66 }
67
68 pub fn get_allocated(&self) -> usize {
70 self.allocated_bytes
71 }
72
73 pub fn get_max_bytes(&self) -> Option<usize> {
75 self.config.max_bytes
76 }
77
78 pub fn can_allocate(&self, bytes: usize) -> bool {
80 if let Some(max_bytes) = self.config.max_bytes {
81 self.allocated_bytes + bytes <= max_bytes
82 } else {
83 true
84 }
85 }
86
87 pub fn available_bytes(&self) -> Option<usize> {
89 self.config
90 .max_bytes
91 .map(|max| max.saturating_sub(self.allocated_bytes))
92 }
93}
94
95impl Default for Heap {
96 fn default() -> Self {
97 Self::new(HeapConfig::default())
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104
105 #[test]
106 fn test_heap_unlimited() {
107 let mut heap = Heap::new(HeapConfig::unlimited());
108 assert!(heap.allocate(1000).is_ok());
109 assert!(heap.allocate(1000000).is_ok());
110 assert_eq!(heap.get_allocated(), 1001000);
111 }
112
113 #[test]
114 fn test_heap_limited() {
115 let mut heap = Heap::new(HeapConfig::with_limit(1000));
116 assert!(heap.allocate(500).is_ok());
117 assert!(heap.allocate(400).is_ok());
118 assert_eq!(heap.get_allocated(), 900);
119
120 let result = heap.allocate(200);
122 assert!(result.is_err());
123 if let Err(JErrorType::RangeError(msg)) = result {
124 assert_eq!(msg, "Out of memory");
125 }
126 }
127
128 #[test]
129 fn test_heap_deallocate() {
130 let mut heap = Heap::new(HeapConfig::with_limit(1000));
131 heap.allocate(500).unwrap();
132 heap.deallocate(300);
133 assert_eq!(heap.get_allocated(), 200);
134
135 assert!(heap.allocate(700).is_ok());
137 }
138
139 #[test]
140 fn test_heap_can_allocate() {
141 let heap = Heap::new(HeapConfig::with_limit(1000));
142 assert!(heap.can_allocate(500));
143 assert!(heap.can_allocate(1000));
144 assert!(!heap.can_allocate(1001));
145 }
146
147 #[test]
148 fn test_heap_available_bytes() {
149 let mut heap = Heap::new(HeapConfig::with_limit(1000));
150 assert_eq!(heap.available_bytes(), Some(1000));
151 heap.allocate(300).unwrap();
152 assert_eq!(heap.available_bytes(), Some(700));
153
154 let unlimited = Heap::new(HeapConfig::unlimited());
155 assert_eq!(unlimited.available_bytes(), None);
156 }
157}