ndata/
heap.rs

1#![cfg_attr(feature = "no_std_support", no_std)]
2
3extern crate alloc;
4use crate::usizemap::UsizeMap;
5
6// Use alloc::vec::Vec when the no_std_support feature is enabled
7#[cfg(feature="no_std_support")]
8use alloc::vec::Vec;
9// If std is available (default), Vec is used from the standard library prelude
10#[cfg(not(feature="no_std_support"))]
11use std::vec::Vec;
12
13use core::fmt::{self, Debug};
14
15// Internal struct to hold the data and its reference count.
16// Not public, as it's an implementation detail of Heap.
17#[derive(Debug)]
18struct Blob<T> {
19    data: T,
20    count: usize,
21}
22
23/// A reference counting container for objects of a given type with basic
24/// garbage collection based on reference counts reaching zero.
25///
26/// Keys are `usize` indices returned by `push`.
27pub struct Heap<T> {
28    data: UsizeMap<Blob<T>>,
29}
30
31// Implement Debug manually to avoid requiring T: Debug for the struct definition,
32// but require it for the Debug implementation.
33impl<T: Debug> Debug for Heap<T> {
34    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35        f.debug_struct("Heap")
36         .field("data", &self.data)
37         .finish()
38    }
39}
40
41impl<T> Heap<T> {
42    /// Creates a new, empty `Heap`.
43    #[inline]
44    pub fn new() -> Heap<T> {
45        Heap {
46            data: UsizeMap::new(),
47        }
48    }
49
50    /// Pushes a value onto the heap, returning a stable `usize` key.
51    /// The initial reference count is 1.
52    pub fn push(&mut self, data: T) -> usize {
53        let blob = Blob {
54            data,
55            count: 1,
56        };
57        self.data.insert(blob)
58    }
59
60    /// Returns a mutable reference to the value associated with the given key.
61    ///
62    /// # Panics
63    /// Panics if the `index` is not a valid key.
64    pub fn get(&mut self, index: usize) -> &mut T {
65        &mut self.data.get_mut(index).expect("Heap::get: Invalid index").data
66    }
67
68    /// Returns a mutable reference to the value associated with the key, if it exists.
69    pub fn try_get(&mut self, index: usize) -> Option<&mut T> {
70        self.data.get_mut(index).map(|blob| &mut blob.data)
71    }
72
73    /// Checks if the heap contains a value for the specified key.
74    pub fn contains_key(&self, index: usize) -> bool {
75        self.data.contains_key(index)
76    }
77
78    /// Returns the current reference count for the value associated with the key.
79    /// Returns 0 if the key does not exist.
80    pub fn count(&mut self, index: usize) -> usize {
81        self.data.get_mut(index).map(|b| b.count).unwrap_or(0)
82    }
83
84    /// Increments the reference count for the value associated with the key.
85    ///
86    /// # Panics
87    /// Panics if the `index` is not valid.
88    pub fn incr(&mut self, index: usize) {
89        if let Some(blob) = self.data.get_mut(index) {
90            blob.count += 1;
91        } else {
92            panic!("Heap::incr: Invalid index {}", index);
93        }
94    }
95
96    /// Decrements the reference count. If it reaches zero, the value is removed.
97    ///
98    /// # Panics
99    /// Panics if the `index` is not valid.
100    pub fn decr(&mut self, index: usize) {
101        // Step 1: Check the count and decide if we need to remove.
102        // We CANNOT call remove() inside this block because self.data is borrowed.
103        let should_remove = if let Some(blob) = self.data.get_mut(index) {
104            if blob.count > 1 {
105                blob.count -= 1;
106                false
107            } else {
108                // count is 1 (or 0, which shouldn't happen), so we remove it.
109                true
110            }
111        } else {
112            panic!("Heap::decr: Invalid index {}", index);
113        };
114
115        // Step 2: Perform removal if necessary (mutable borrow has ended)
116        if should_remove {
117            self.data.remove(index);
118        }
119    }
120
121    /// Forcibly removes an item from the heap regardless of its reference count.
122    /// Returns the data if it existed.
123    ///
124    /// Useful for error recovery or session cleanup.
125    pub fn free(&mut self, index: usize) -> Option<T> {
126        self.data.remove(index).map(|b| b.data)
127    }
128
129    /// Returns a vector containing all the keys currently present.
130    pub fn keys(&self) -> Vec<usize> {
131        self.data.keys()
132    }
133
134    /// Clears the heap, removing all values.
135    pub fn clear(&mut self) {
136        self.data.clear();
137    }
138
139    /// Shrinks the underlying memory storage to fit the current data.
140    pub fn shrink_to_fit(&mut self) {
141        self.data.shrink_to_fit();
142    }
143}
144
145// Implement Default trait for Heap<T>
146impl<T> Default for Heap<T> {
147    fn default() -> Self {
148        Self::new()
149    }
150}