roussillon_memory/
heap.rs

1use std::cell::RefCell;
2use std::fmt::{Debug, Formatter};
3use std::rc::Rc;
4use roussillon_type_system::types::concept::{DataType, Type};
5use roussillon_type_system::value::concept::{DataValue, ValueCell};
6use roussillon_type_system::value::error::TypeResult;
7use roussillon_type_system::value::reference::Reference;
8use crate::region::{Allocator, Dereference, Region, DroppableRegion};
9
10pub struct HeapReferenceType {
11    generation: usize,
12    t: Type
13}
14
15impl HeapReferenceType {
16    pub fn to_rc(self) -> Rc<Self> { Rc::new(self) }
17}
18
19impl DataType for HeapReferenceType {
20    fn size(&self) -> usize {
21        16
22    }
23
24    fn typename(&self) -> String {
25        format!("@{}&{}", self.generation, self.t)
26    }
27
28    fn construct_from_raw(&self, raw: &[u8]) -> TypeResult<ValueCell> {
29        let (raw_generation, raw_reference) = raw.split_at(8);
30        let generation = usize::from_be_bytes(raw_generation.try_into().unwrap());
31        let raw_reference = usize::from_be_bytes(raw_reference.try_into().unwrap());
32        let reference = Reference::new(self.t.clone(), raw_reference);
33        Ok(HeapReference{ generation, reference }.to_cell())
34    }
35}
36
37#[derive(Clone, Debug)]
38pub struct HeapReference {
39    generation: usize,
40    reference: Reference,
41}
42
43impl HeapReference {
44    pub fn reference(&self) -> &Reference {
45        &self.reference
46    }
47
48    pub fn generation(&self) -> usize { self.generation }
49    pub fn to_cell(self) -> ValueCell { Rc::new(RefCell::new(self)) }
50}
51
52impl DataValue for HeapReference {
53    fn data_type(&self) -> Type {
54        HeapReferenceType{ generation: self.generation, t: self.reference.referenced().clone() }.to_rc()
55    }
56
57    fn raw(&self) -> Vec<u8> {
58        let mut raw = Vec::new();
59        raw.extend_from_slice(&self.generation.to_be_bytes());
60        raw.extend_from_slice(&self.reference.raw());
61        raw
62    }
63
64    fn set(&mut self, raw: &[u8]) {
65        let (raw_generation, raw_reference) = raw.split_at(8);
66        self.generation = usize::from_be_bytes(raw_generation.try_into().unwrap());
67        let raw_reference = usize::from_be_bytes(raw_reference.try_into().unwrap());
68        self.reference = Reference::new(self.reference.referenced().clone(), raw_reference);
69    }
70}
71
72#[derive(Default)]
73pub struct Heap {
74    raw: Vec<DroppableRegion>,
75    current: Option<usize>,
76}
77
78impl Heap {
79    pub fn new() -> Self { Heap { raw: Vec::new(), current: None } }
80    pub fn current_generation(&self) -> Option<usize> { self.current }
81    pub fn next_generation(&mut self) -> &mut Region {
82        self.current = match self.current {
83            None => Some(0),
84            Some(_) => Some(self.raw.len()), // current size IS next index
85        };
86        self.raw.push(DroppableRegion::Alive(Region::default()));
87        self.raw.last_mut().unwrap().unwrap_mut() // Very confident unwrap()s
88    }
89    pub fn clear(&mut self, generation: usize) { self.raw[generation] = DroppableRegion::Dropped; }
90    pub fn is_alive(&self, generation: usize) -> bool { self.raw[generation].is_alive() }
91}
92
93impl Allocator<HeapReference> for Heap {
94    fn allocate(&mut self, cell: ValueCell) -> HeapReference {
95        let current = self.current_generation().unwrap_or_else(|| {
96            self.next_generation();
97            self.current_generation().unwrap()
98        });
99        if let Some(DroppableRegion::Alive(region)) = self.raw.get_mut(current) {
100            let r = region.allocate(cell);
101            HeapReference { generation: self.current.unwrap(), reference: r }
102        } else {
103            panic!("Invalid region in heap.")
104        }
105    }
106}
107
108impl Dereference<HeapReference> for Heap {
109    fn dereference(&self, reference: HeapReference) -> Option<ValueCell> {
110        if let DroppableRegion::Alive(r) = self.raw.get(reference.generation)? {
111            r.dereference(reference.reference)
112        } else {
113            None
114        }
115    }
116
117    fn validate(&self, reference: &HeapReference) -> bool {
118        if !self.is_alive(reference.generation) || reference.generation >= self.raw.len() {
119            return false;
120        }
121        if let Some(DroppableRegion::Alive(region)) = self.raw.get(reference.generation) {
122            region.validate(&reference.reference)
123        } else {
124            false
125        }
126    }
127}
128
129impl Debug for Heap {
130    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
131        writeln!(f, "Heap [{:?}]", self.current)?;
132        for (i, r) in self.raw.iter().enumerate() {
133            writeln!(f, "  - Region #{} : {}", i, match r {
134                DroppableRegion::Alive(region) => format!("Alive (&{})", region.len()),
135                DroppableRegion::Dropped => "Dropped".to_string()
136            })?;
137        }
138        Ok(())
139    }
140}