roussillon_memory/
heap.rs1use 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()), };
86 self.raw.push(DroppableRegion::Alive(Region::default()));
87 self.raw.last_mut().unwrap().unwrap_mut() }
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}