1use crate::dif::interface::DIFResolveReferenceError;
2use crate::dif::reference::DIFReference;
3use crate::dif::r#type::DIFTypeDefinition;
4use crate::dif::update::{DIFKey, DIFUpdateData};
5use crate::dif::value::DIFReferenceNotFoundError;
6use crate::references::observers::{ObserveOptions, Observer, TransceiverId};
7use crate::references::reference::ReferenceMutability;
8use crate::runtime::RuntimeInternal;
9use crate::stdlib::rc::Rc;
10use crate::stdlib::vec::Vec;
11use crate::values::value_container::ValueContainer;
12use crate::{
13 dif::{
14 interface::{
15 DIFApplyError, DIFCreatePointerError, DIFInterface,
16 DIFObserveError, DIFUpdateError,
17 },
18 value::DIFValueContainer,
19 },
20 references::reference::Reference,
21 values::pointer::PointerAddress,
22};
23use core::prelude::rust_2024::*;
24use core::result::Result;
25
26impl RuntimeInternal {
27 fn resolve_in_memory_reference(
28 &self,
29 address: &PointerAddress,
30 ) -> Option<Reference> {
31 self.memory.borrow().get_reference(address).cloned()
32 }
33 async fn resolve_reference(
35 &self,
36 address: &PointerAddress,
37 ) -> Option<Reference> {
38 self.memory.borrow().get_reference(address).cloned()
39 }
40}
41
42impl DIFInterface for RuntimeInternal {
43 fn update(
44 &self,
45 source_id: TransceiverId,
46 address: PointerAddress,
47 update: &DIFUpdateData,
48 ) -> Result<(), DIFUpdateError> {
49 let reference = self
50 .resolve_in_memory_reference(&address)
51 .ok_or(DIFUpdateError::ReferenceNotFound)?;
52 match update {
53 DIFUpdateData::Set { key, value } => {
54 let value_container = value.to_value_container(&self.memory)?;
55 match key {
56 DIFKey::Text(key) => reference.try_set_property(
57 source_id,
58 update,
59 key,
60 value_container,
61 )?,
62 DIFKey::Index(key) => reference.try_set_property(
63 source_id,
64 update,
65 *key,
66 value_container,
67 )?,
68 DIFKey::Value(key) => {
69 let key = key.to_value_container(&self.memory)?;
70 reference.try_set_property(
71 source_id,
72 update,
73 &key,
74 value_container,
75 )?
76 }
77 }
78 }
79 DIFUpdateData::Replace { value } => reference.try_replace(
80 source_id,
81 update,
82 value.to_value_container(&self.memory)?,
83 )?,
84 DIFUpdateData::Append { value } => reference.try_append_value(
85 source_id,
86 update,
87 value.to_value_container(&self.memory)?,
88 )?,
89 DIFUpdateData::Clear => reference.try_clear(source_id)?,
90 DIFUpdateData::Delete { key } => match key {
91 DIFKey::Text(key) => {
92 reference.try_delete_property(source_id, update, key)?
93 }
94 DIFKey::Index(key) => {
95 reference.try_delete_property(source_id, update, *key)?
96 }
97 DIFKey::Value(key) => {
98 let key = key.to_value_container(&self.memory)?;
99 reference.try_delete_property(source_id, update, &key)?
100 }
101 },
102 DIFUpdateData::ListSplice {
103 start,
104 delete_count,
105 items,
106 } => {
107 reference.try_list_splice(
108 source_id,
109 update,
110 *start..(start + delete_count),
111 items
112 .iter()
113 .map(|item| item.to_value_container(&self.memory))
114 .collect::<Result<
115 Vec<ValueContainer>,
116 DIFReferenceNotFoundError,
117 >>()?,
118 )?
119 }
120 };
121
122 Ok(())
123 }
124
125 fn apply(
126 &self,
127 callee: DIFValueContainer,
128 value: DIFValueContainer,
129 ) -> Result<DIFValueContainer, DIFApplyError> {
130 core::todo!("#400 Undescribed by author.")
131 }
132
133 fn create_pointer(
134 &self,
135 value: DIFValueContainer,
136 allowed_type: Option<DIFTypeDefinition>,
137 mutability: ReferenceMutability,
138 ) -> Result<PointerAddress, DIFCreatePointerError> {
139 let container = value.to_value_container(&self.memory)?;
140 let type_container = if let Some(allowed_type) = &allowed_type {
141 core::todo!(
142 "FIXME: Implement type_container creation from DIFTypeDefinition"
143 )
144 } else {
145 None
146 };
147 let reference = Reference::try_new_from_value_container(
148 container,
149 type_container,
150 None,
151 mutability,
152 )?;
153 let address = self.memory.borrow_mut().register_reference(&reference);
154 Ok(address)
155 }
156
157 async fn resolve_pointer_address_external(
158 &self,
159 address: PointerAddress,
160 ) -> Result<DIFReference, DIFResolveReferenceError> {
161 let reference = self.resolve_in_memory_reference(&address);
162 match reference {
163 Some(ptr) => Ok(DIFReference::from_reference(&ptr, &self.memory)),
164 None => {
165 core::todo!("#399 Implement async resolution of references")
166 }
167 }
168 }
169
170 fn resolve_pointer_address_in_memory(
171 &self,
172 address: PointerAddress,
173 ) -> Result<DIFReference, DIFResolveReferenceError> {
174 let reference = self.resolve_in_memory_reference(&address);
175 match reference {
176 Some(ptr) => Ok(DIFReference::from_reference(&ptr, &self.memory)),
177 None => Err(DIFResolveReferenceError::ReferenceNotFound),
178 }
179 }
180
181 fn observe_pointer(
182 &self,
183 transceiver_id: TransceiverId,
184 address: PointerAddress,
185 options: ObserveOptions,
186 callback: impl Fn(&DIFUpdateData, TransceiverId) + 'static,
187 ) -> Result<u32, DIFObserveError> {
188 let reference = self
189 .resolve_in_memory_reference(&address)
190 .ok_or(DIFObserveError::ReferenceNotFound)?;
191 Ok(reference.observe(Observer {
192 transceiver_id,
193 options,
194 callback: Rc::new(callback),
195 })?)
196 }
197
198 fn update_observer_options(
199 &self,
200 address: PointerAddress,
201 observer_id: u32,
202 options: ObserveOptions,
203 ) -> Result<(), DIFObserveError> {
204 let reference = self
205 .resolve_in_memory_reference(&address)
206 .ok_or(DIFObserveError::ReferenceNotFound)?;
207 reference
208 .update_observer_options(observer_id, options)
209 .map_err(DIFObserveError::ObserveError)
210 }
211
212 fn unobserve_pointer(
213 &self,
214 address: PointerAddress,
215 observer_id: u32,
216 ) -> Result<(), DIFObserveError> {
217 let reference = self
218 .resolve_in_memory_reference(&address)
219 .ok_or(DIFObserveError::ReferenceNotFound)?;
220 reference
221 .unobserve(observer_id)
222 .map_err(DIFObserveError::ObserveError)
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use crate::dif::interface::DIFInterface;
229 use crate::dif::representation::DIFValueRepresentation;
230 use crate::dif::update::{DIFUpdate, DIFUpdateData};
231 use crate::dif::value::{DIFValue, DIFValueContainer};
232 use crate::references::observers::ObserveOptions;
233 use crate::references::reference::ReferenceMutability;
234 use crate::runtime::Runtime;
235 use crate::runtime::memory::Memory;
236 use crate::stdlib::rc::Rc;
237 use crate::values::core_values::endpoint::Endpoint;
238 use crate::values::core_values::map::Map;
239 use crate::values::value_container::ValueContainer;
240 use core::cell::RefCell;
241 use datex_core::runtime::RuntimeConfig;
242
243 #[test]
244 fn struct_serde() {
245 let memory = RefCell::new(Memory::new(Endpoint::default()));
246 let map = ValueContainer::from(Map::from(vec![
247 ("a".to_string(), 1.into()),
248 ("b".to_string(), "text".into()),
249 ]));
250 let dif_value = DIFValueContainer::from_value_container(&map, &memory);
251 let _ = serde_json::to_string(&dif_value).unwrap();
252 }
253
254 #[test]
255 fn test_create_and_observe_pointer() {
256 let runtime = Runtime::init_native(RuntimeConfig::default()).internal;
257 let pointer_address = runtime
258 .create_pointer(
259 DIFValueContainer::Value(DIFValue::from(
260 DIFValueRepresentation::String("Hello, world!".to_string()),
261 )),
262 None,
263 ReferenceMutability::Mutable,
264 )
265 .expect("Failed to create pointer");
266
267 let observed = Rc::new(RefCell::new(None));
268 let observed_clone = observed.clone();
269
270 let observer_id = Rc::new(RefCell::new(None));
271 let observer_id_clone = observer_id.clone();
272 let runtime_clone = runtime.clone();
273 let pointer_address_clone = pointer_address.clone();
274
275 observer_id.replace(Some(
277 runtime
278 .observe_pointer(
279 0,
280 pointer_address_clone.clone(),
281 ObserveOptions::default(),
282 move |update, _| {
283 println!("Observed pointer value: {:?}", update);
284 observed_clone.replace(Some(update.clone()));
285 runtime_clone
287 .unobserve_pointer(
288 pointer_address_clone.clone(),
289 observer_id_clone.borrow().unwrap(),
290 )
291 .unwrap();
292 },
293 )
294 .expect("Failed to observe pointer"),
295 ));
296
297 runtime
299 .update(
300 1,
301 pointer_address.clone(),
302 &DIFUpdateData::replace(DIFValue::from(
303 DIFValueRepresentation::String("Hello, Datex!".to_string()),
304 )),
305 )
306 .expect("Failed to update pointer");
307
308 let observed_value = observed.borrow();
310 assert_eq!(
311 *observed_value,
312 Some(DIFUpdateData::replace(DIFValue::from(
313 DIFValueRepresentation::String("Hello, Datex!".to_string(),)
314 )))
315 );
316
317 assert!(
319 runtime
320 .unobserve_pointer(
321 pointer_address.clone(),
322 observer_id.borrow().unwrap()
323 )
324 .is_err()
325 );
326 }
327}