datex_core/runtime/
memory.rs1use crate::libs::core::{CoreLibPointerId, load_core_lib};
2use crate::references::reference::Reference;
3use crate::references::type_reference::TypeReference;
4use crate::references::value_reference::ValueReference;
5use crate::types::error::IllegalTypeError;
6use crate::types::type_container::TypeContainer;
7use crate::utils::time::Time;
8use crate::values::pointer::PointerAddress;
9use datex_core::global::protocol_structures::instructions::RawFullPointerAddress;
10use datex_core::values::core_values::endpoint::Endpoint;
11use std::cell::RefCell;
12use std::collections::HashMap;
13use std::io::Cursor;
14use std::rc::Rc;
15#[derive(Debug, Default)]
18pub struct Memory {
19 local_endpoint: Endpoint,
20 local_counter: u64, last_timestamp: u64, pointers: HashMap<PointerAddress, Reference>, }
24
25impl Memory {
26 pub fn new(endpoint: Endpoint) -> Memory {
28 let mut memory = Memory {
29 local_endpoint: endpoint,
30 local_counter: 0,
31 last_timestamp: 0,
32 pointers: HashMap::new(),
33 };
34 load_core_lib(&mut memory);
36 memory
37 }
38
39 pub fn register_reference(
43 &mut self,
44 reference: &Reference,
45 ) -> PointerAddress {
46 let pointer_address = reference.pointer_address();
47 if let Some(ref address) = pointer_address
49 && self.pointers.contains_key(address)
50 {
51 return address.clone();
52 }
53 let pointer_address = if let Some(address) = pointer_address {
55 address
56 } else {
57 let pointer_address = self.get_new_local_address();
58 reference.set_pointer_address(pointer_address.clone());
59 pointer_address
60 };
61
62 self.pointers
63 .insert(pointer_address.clone(), reference.clone());
64 pointer_address
65 }
66
67 pub fn get_reference(
69 &self,
70 pointer_address: &PointerAddress,
71 ) -> Option<&Reference> {
72 self.pointers.get(pointer_address)
73 }
74
75 pub fn get_value_reference(
76 &self,
77 pointer_address: &PointerAddress,
78 ) -> Option<&Rc<RefCell<ValueReference>>> {
79 self.get_reference(pointer_address).and_then(|r| match r {
80 Reference::ValueReference(v) => Some(v),
81 _ => None,
82 })
83 }
84
85 pub fn get_type_reference(
86 &self,
87 pointer_address: &PointerAddress,
88 ) -> Option<&Rc<RefCell<TypeReference>>> {
89 self.get_reference(pointer_address).and_then(|r| match r {
90 Reference::TypeReference(t) => Some(t),
91 _ => None,
92 })
93 }
94
95 pub fn get_core_reference(
97 &self,
98 pointer_id: CoreLibPointerId,
99 ) -> &Reference {
100 self.get_reference(&pointer_id.into())
101 .expect("core reference not found in memory")
102 }
103
104 pub fn get_core_type(
106 &self,
107 pointer_id: CoreLibPointerId,
108 ) -> Result<TypeContainer, IllegalTypeError> {
109 let reference = self
110 .get_reference(&pointer_id.into())
111 .ok_or(IllegalTypeError::TypeNotFound)?;
112 match &reference {
113 Reference::TypeReference(def) => {
114 Ok(TypeContainer::TypeReference(def.clone()))
115 }
116 _ => Err(IllegalTypeError::TypeNotFound),
117 }
118 }
119
120 pub fn get_core_type_unchecked(
123 &self,
124 pointer_id: CoreLibPointerId,
125 ) -> TypeContainer {
126 self.get_core_type(pointer_id)
128 .expect("core type not found or cannot be used as a type")
129 }
130
131 pub fn get_pointer_address_from_raw_full_address(
134 &self,
135 raw_address: RawFullPointerAddress,
136 ) -> PointerAddress {
137 if raw_address.endpoint == self.local_endpoint {
138 PointerAddress::Local(raw_address.id)
139 } else {
140 let writer = Cursor::new(Vec::new());
142 let mut bytes = writer.into_inner();
143 bytes.extend_from_slice(&raw_address.id);
144 PointerAddress::Remote(<[u8; 26]>::try_from(bytes).unwrap())
145 }
146 }
147
148 pub fn get_new_local_address(&mut self) -> PointerAddress {
150 let timestamp = Time::now();
151 if timestamp != self.last_timestamp {
153 self.last_timestamp = timestamp;
154 self.local_counter = 0;
155 }
156 else {
158 self.local_counter += 1;
159 }
160 self.local_counter += 1;
161
162 let id: [u8; 5] = [
164 (timestamp >> 24) as u8,
165 (timestamp >> 16) as u8,
166 (timestamp >> 8) as u8,
167 timestamp as u8,
168 (self.local_counter & 0xFF) as u8,
169 ];
170 PointerAddress::Local(id)
171 }
172}
173
174impl Reference {
175 pub fn ensure_pointer_address(
178 &self,
179 memory: &RefCell<Memory>,
180 ) -> PointerAddress {
181 self.pointer_address()
182 .unwrap_or_else(|| memory.borrow_mut().register_reference(self))
183 }
184}