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