1use std::cell::RefCell;
10
11pub struct HeapArena {
16 generations: Vec<Generation>,
18}
19
20struct Generation {
21 strings: Vec<String>,
23 buffers: Vec<Vec<u8>>,
25}
26
27impl Default for HeapArena {
28 fn default() -> Self {
29 Self::new()
30 }
31}
32
33impl HeapArena {
34 pub fn new() -> Self {
35 HeapArena {
36 generations: vec![Generation {
37 strings: Vec::new(),
38 buffers: Vec::new(),
39 }],
40 }
41 }
42
43 pub fn push(&mut self) {
45 self.generations.push(Generation {
46 strings: Vec::new(),
47 buffers: Vec::new(),
48 });
49 }
50
51 pub fn pop(&mut self) {
53 if self.generations.len() > 1 {
54 self.generations.pop();
55 }
56 }
57
58 pub fn free_current(&mut self) {
60 if let Some(gen) = self.generations.last_mut() {
61 gen.strings.clear();
62 gen.buffers.clear();
63 }
64 }
65
66 pub fn alloc_string(&mut self, s: String) -> &str {
68 if let Some(gen) = self.generations.last_mut() {
69 gen.strings.push(s);
70 gen.strings.last().map(|s| s.as_str()).unwrap()
71 } else {
72 panic!("No generation available")
73 }
74 }
75
76 pub fn alloc_bytes(&mut self, bytes: Vec<u8>) -> &[u8] {
78 if let Some(gen) = self.generations.last_mut() {
79 gen.buffers.push(bytes);
80 gen.buffers.last().map(|b| b.as_slice()).unwrap()
81 } else {
82 panic!("No generation available")
83 }
84 }
85
86 pub fn depth(&self) -> usize {
88 self.generations.len()
89 }
90}
91
92thread_local! {
93 static HEAP: RefCell<HeapArena> = RefCell::new(HeapArena::new());
94}
95
96pub fn pushheap() {
98 HEAP.with(|h| h.borrow_mut().push());
99}
100
101pub fn popheap() {
103 HEAP.with(|h| h.borrow_mut().pop());
104}
105
106pub fn freeheap() {
108 HEAP.with(|h| h.borrow_mut().free_current());
109}
110
111pub fn zalloc<T: Default>() -> Box<T> {
113 Box::default()
114}
115
116pub fn zshcalloc<T: Default>() -> Box<T> {
118 Box::default()
119}
120
121pub fn zrealloc<T>(v: &mut Vec<T>, new_size: usize)
123where
124 T: Default + Clone,
125{
126 v.resize(new_size, T::default());
127}
128
129pub fn zfree<T>(_ptr: Box<T>) {
131 }
133
134pub fn zsfree(_s: String) {
136 }
138
139pub fn dupstring(s: &str) -> String {
141 s.to_string()
142}
143
144pub fn dupstring_wlen(s: &str, len: usize) -> String {
146 s.chars().take(len).collect()
147}
148
149pub fn zhalloc_string(s: &str) -> String {
151 s.to_string()
152}
153
154pub fn zheapptr<T>(_ptr: &T) -> bool {
157 true
158}
159
160pub fn hrealloc(old: Vec<u8>, new_size: usize) -> Vec<u8> {
162 let mut v = old;
163 v.resize(new_size, 0);
164 v
165}
166
167pub fn zarrdup(arr: &[String]) -> Vec<String> {
169 arr.to_vec()
170}
171
172pub fn arrdup_max(arr: &[String], max: usize) -> Vec<String> {
174 arr.iter().take(max).cloned().collect()
175}
176
177pub fn arrlen<T>(arr: &[T]) -> usize {
179 arr.len()
180}
181
182pub fn arrlen_lt<T>(arr: &[T], n: usize) -> bool {
184 arr.len() < n
185}
186
187pub fn arrlen_le<T>(arr: &[T], n: usize) -> bool {
189 arr.len() <= n
190}
191
192pub fn arrlen_eq<T>(arr: &[T], n: usize) -> bool {
194 arr.len() == n
195}
196
197pub fn arrlen_gt<T>(arr: &[T], n: usize) -> bool {
199 arr.len() > n
200}
201
202pub fn sepjoin(arr: &[String], sep: Option<&str>) -> String {
204 arr.join(sep.unwrap_or(" "))
205}
206
207pub fn sepsplit(s: &str, sep: &str, allow_empty: bool) -> Vec<String> {
209 if allow_empty {
210 s.split(sep).map(|s| s.to_string()).collect()
211 } else {
212 s.split(sep)
213 .filter(|s| !s.is_empty())
214 .map(|s| s.to_string())
215 .collect()
216 }
217}
218
219pub fn zshcalloc_buf(size: usize) -> Vec<u8> {
221 vec![0u8; size]
222}
223
224pub fn zalloc_buf(size: usize) -> Vec<u8> {
226 Vec::with_capacity(size)
227}
228
229pub fn ztrdup(s: &str) -> String {
231 s.to_string()
232}
233
234pub fn ztrduppfx(s: &str, len: usize) -> String {
236 s.chars().take(len).collect()
237}
238
239pub fn bicat(s1: &str, s2: &str) -> String {
241 format!("{}{}", s1, s2)
242}
243
244pub fn tricat(s1: &str, s2: &str, s3: &str) -> String {
246 format!("{}{}{}", s1, s2, s3)
247}
248
249pub fn dyncat(s1: &str, s2: &str) -> String {
251 format!("{}{}", s1, s2)
252}
253
254pub fn strend(s: &str) -> Option<char> {
256 s.chars().last()
257}
258
259pub fn appstr(base: &mut String, append: &str) {
261 base.push_str(append);
262}
263
264#[derive(Default, Debug, Clone)]
266pub struct MemStats {
267 pub heap_count: usize,
268 pub heap_total: usize,
269 pub heap_used: usize,
270 pub alloc_count: usize,
271 pub free_count: usize,
272}
273
274impl MemStats {
275 pub fn new() -> Self {
276 Self::default()
277 }
278}
279
280pub fn get_mem_stats() -> MemStats {
282 MemStats::new()
283}
284
285pub struct MemContext {
287 heap_depth: usize,
288}
289
290impl MemContext {
291 pub fn save() -> Self {
292 let depth = HEAP.with(|h| h.borrow().depth());
293 MemContext { heap_depth: depth }
294 }
295
296 pub fn restore(self) {
297 HEAP.with(|h| {
298 let mut heap = h.borrow_mut();
299 while heap.depth() > self.heap_depth {
300 heap.pop();
301 }
302 });
303 }
304}
305
306pub fn zcontext_save() -> MemContext {
308 MemContext::save()
309}
310
311pub fn zcontext_restore(ctx: MemContext) {
313 ctx.restore();
314}
315
316pub fn queue_signals() {}
318
319pub fn unqueue_signals() {}
321
322#[cfg(test)]
323mod tests {
324 use super::*;
325
326 #[test]
327 fn test_heap_push_pop() {
328 let mut arena = HeapArena::new();
329 assert_eq!(arena.depth(), 1);
330
331 arena.push();
332 assert_eq!(arena.depth(), 2);
333
334 arena.alloc_string("test".to_string());
335
336 arena.pop();
337 assert_eq!(arena.depth(), 1);
338 }
339
340 #[test]
341 fn test_heap_free_current() {
342 let mut arena = HeapArena::new();
343
344 arena.alloc_string("test1".to_string());
345 arena.alloc_bytes(vec![1, 2, 3]);
346
347 arena.free_current();
348 assert_eq!(arena.depth(), 1);
350 }
351
352 #[test]
353 fn test_nested_generations() {
354 let mut arena = HeapArena::new();
355
356 arena.alloc_string("level1".to_string());
357
358 arena.push();
359 arena.alloc_string("level2".to_string());
360
361 arena.push();
362 arena.alloc_string("level3".to_string());
363
364 assert_eq!(arena.depth(), 3);
365
366 arena.pop();
367 assert_eq!(arena.depth(), 2);
368
369 arena.pop();
370 assert_eq!(arena.depth(), 1);
371 }
372
373 #[test]
374 fn test_dupstring() {
375 let s = dupstring("hello");
376 assert_eq!(s, "hello");
377 }
378
379 #[test]
380 fn test_dupstring_wlen() {
381 let s = dupstring_wlen("hello world", 5);
382 assert_eq!(s, "hello");
383 }
384
385 #[test]
386 fn test_global_heap() {
387 pushheap();
388 pushheap();
389 popheap();
390 popheap();
391 }
393}