datex_core/runtime/
memory.rs1use crate::{
2 collections::HashMap,
3 global::protocol_structures::instructions::RawRemotePointerAddress,
4 libs::core::{CoreLibPointerId, load_core_lib},
5 shared_values::{
6 shared_container::SharedContainer,
7 shared_type_container::SharedTypeContainer,
8 shared_value_container::SharedValueContainer,
9 },
10 types::error::IllegalTypeError,
11 values::core_values::endpoint::Endpoint,
12};
13use binrw::io::Cursor;
14use core::{cell::RefCell, result::Result};
15
16use crate::{
17 prelude::*,
18 shared_values::{
19 pointer::Pointer,
20 pointer_address::{
21 OwnedPointerAddress, PointerAddress, ReferencedPointerAddress,
22 },
23 },
24};
25
26#[derive(Debug, Default)]
27pub struct Memory {
28 local_endpoint: Endpoint,
29 local_counter: u64, last_timestamp: u64, pointers: HashMap<PointerAddress, SharedContainer>, }
33
34impl Memory {
35 pub fn new(endpoint: Endpoint) -> Memory {
37 let mut memory = Memory {
38 local_endpoint: endpoint,
39 local_counter: 0,
40 last_timestamp: 0,
41 pointers: HashMap::new(),
42 };
43 load_core_lib(&mut memory);
45 memory
46 }
47
48 pub fn register_shared_container(&mut self, reference: &SharedContainer) {
52 let pointer_address = reference.pointer_address();
53 self.pointers
55 .entry(pointer_address)
56 .or_insert_with(|| reference.clone());
57 }
58
59 pub fn get_reference(
61 &self,
62 pointer_address: &PointerAddress,
63 ) -> Option<&SharedContainer> {
64 self.pointers.get(pointer_address)
65 }
66
67 pub fn get_value_reference(
68 &self,
69 pointer_address: &PointerAddress,
70 ) -> Option<&Rc<RefCell<SharedValueContainer>>> {
71 self.get_reference(pointer_address).and_then(|r| match r {
72 SharedContainer::Value(v) => Some(v),
73 _ => None,
74 })
75 }
76
77 pub fn get_type_reference(
78 &self,
79 pointer_address: &PointerAddress,
80 ) -> Option<&Rc<RefCell<SharedTypeContainer>>> {
81 self.get_reference(pointer_address).and_then(|r| match r {
82 SharedContainer::Type(t) => Some(t),
83 _ => None,
84 })
85 }
86
87 pub fn get_core_reference(
89 &self,
90 pointer_id: CoreLibPointerId,
91 ) -> &SharedContainer {
92 self.get_reference(&pointer_id.into())
93 .expect("core reference not found in memory")
94 }
95
96 pub fn get_core_type_reference(
98 &self,
99 pointer_id: CoreLibPointerId,
100 ) -> Result<Rc<RefCell<SharedTypeContainer>>, IllegalTypeError> {
101 let reference = self
102 .get_reference(&pointer_id.into())
103 .ok_or(IllegalTypeError::TypeNotFound)?;
104 match reference {
105 SharedContainer::Type(def) => Ok(def.clone()),
106 _ => Err(IllegalTypeError::TypeNotFound),
107 }
108 }
109
110 pub fn get_core_type_reference_unchecked(
113 &self,
114 pointer_id: CoreLibPointerId,
115 ) -> Rc<RefCell<SharedTypeContainer>> {
116 self.get_core_type_reference(pointer_id)
118 .expect("core type not found or cannot be used as a type")
119 }
120
121 pub fn get_pointer_address_from_raw_full_address(
124 &self,
125 raw_address: RawRemotePointerAddress,
126 ) -> PointerAddress {
127 if let Ok(endpoint) = raw_address.endpoint()
128 && endpoint == self.local_endpoint
129 {
130 let last_bytes = &raw_address.id[raw_address.id.len() - 5..];
132 PointerAddress::owned(last_bytes.try_into().unwrap())
133 } else {
134 let writer = Cursor::new(Vec::new());
136 let mut bytes = writer.into_inner();
137 bytes.extend_from_slice(&raw_address.id);
138 PointerAddress::Referenced(ReferencedPointerAddress::Remote(
139 <[u8; 26]>::try_from(bytes).unwrap(),
140 ))
141 }
142 }
143
144 pub fn get_new_owned_local_pointer(&mut self) -> Pointer {
146 let timestamp = crate::time::now_ms();
147 if timestamp != self.last_timestamp {
149 self.last_timestamp = timestamp;
150 self.local_counter = 0;
151 }
152 else {
154 self.local_counter += 1;
155 }
156 self.local_counter += 1;
157
158 let id: [u8; 5] = [
160 (timestamp >> 24) as u8,
161 (timestamp >> 16) as u8,
162 (timestamp >> 8) as u8,
163 timestamp as u8,
164 (self.local_counter & 0xFF) as u8,
165 ];
166
167 Pointer::new_owned(OwnedPointerAddress::new(id))
168 }
169}