1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
extern crate alloc;
use crate::usizemap::*;

#[cfg(feature="no_std_support")]
use alloc::vec::Vec;

#[derive(Debug)]
struct Blob<T> {
  data: T,
  count: usize,
}

/// A reference counting container for objects of a given type with automatic garbage collection
#[derive(Debug)]
pub struct Heap<T> {
  data: UsizeMap<Blob<T>>,
}

impl<T: core::fmt::Debug> Heap<T> {
  /// Create a new ```Heap``` of type ```T```.
  pub fn new() -> Heap<T> {
    Heap {
      data: UsizeMap::<Blob<T>>::new(),
    }
  }

  /// Push an instance of type ```T``` to the heap and return a (```usize```) reference to it.
  pub fn push(&mut self, data: T) -> usize {
    let blob = Blob{
      data: data,
      count: 1,
    };
    
    self.data.insert(blob)
  }
  
  /// Return the value for the given data reference.
  pub fn get(&mut self, index:usize) -> &mut T {
    &mut self.data.get_mut(index).unwrap().data
  }

  /// Return the value for the given data reference if it exists.
  pub fn try_get(&mut self, index:usize) -> Option<&mut T> {
    let x = self.data.get_mut(index);
    if x.is_none() { return None }
    Some(&mut x.unwrap().data)
  }

  /// Return the given instance's reference count.
  pub fn count(&mut self, index:usize) -> usize {
    self.data[index].count
  }

  /// Increase the given instance's reference count by one.
  pub fn incr(&mut self, index:usize) {
    self.data.get_mut(index).unwrap().count += 1;
  }
 
  /// Decrease the given instance's reference count by one.
  pub fn decr(&mut self, index: usize) {
    let b = self.data.get_mut(index).unwrap();
    let c = b.count;
    if c == 1 {
      self.data.remove(index);
    }
    else {
      b.count = c-1;
    }
  }
  
  /// List the keys to the data on the heap
  pub fn keys(&self) -> Vec<usize> {
    self.data.keys()
  }
}