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