1use crate::dif::DIFConvertible;
2use crate::dif::{
3 representation::DIFValueRepresentation, r#type::DIFTypeContainer,
4};
5use crate::libs::core::CoreLibPointerId;
6use crate::types::type_container::TypeContainer;
7use crate::values::core_values::decimal::typed_decimal::{
8 DecimalTypeVariant, TypedDecimal,
9};
10use crate::values::core_values::integer::typed_integer::TypedInteger;
11use crate::values::core_values::map::MapKey;
12use crate::values::pointer::PointerAddress;
13use crate::values::value::Value;
14use crate::values::value_container::ValueContainer;
15use datex_core::runtime::memory::Memory;
16use datex_core::values::core_value::CoreValue;
17use serde::{Deserialize, Serialize};
18use std::cell::RefCell;
19
20#[derive(Debug)]
21pub struct DIFReferenceNotFoundError;
22
23#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
25pub struct DIFValue {
26 pub value: DIFValueRepresentation,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub r#type: Option<DIFTypeContainer>,
29}
30impl DIFConvertible for DIFValue {}
31
32impl DIFValue {
33 pub fn to_value(
36 self,
37 memory: &RefCell<Memory>,
38 ) -> Result<Value, DIFReferenceNotFoundError> {
39 Ok(if let Some(r#type) = &self.r#type {
40 self.value.to_value_with_type(r#type, memory)?
41 } else {
42 self.value.to_default_value(memory)?
43 })
44 }
45}
46
47impl DIFValue {
48 pub fn new(
49 value: DIFValueRepresentation,
50 r#type: Option<impl Into<DIFTypeContainer>>,
51 ) -> Self {
52 DIFValue {
53 value,
54 r#type: r#type.map(Into::into),
55 }
56 }
57 pub fn as_container(&self) -> DIFValueContainer {
58 DIFValueContainer::from(self.clone())
59 }
60}
61
62impl From<DIFValueRepresentation> for DIFValue {
63 fn from(value: DIFValueRepresentation) -> Self {
64 DIFValue {
65 value,
66 r#type: None,
67 }
68 }
69}
70
71#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
73#[serde(untagged)]
74pub enum DIFValueContainer {
75 Value(DIFValue),
76 Reference(PointerAddress),
77}
78impl DIFConvertible for DIFValueContainer {}
79
80impl DIFValueContainer {
81 pub fn to_value_container(
84 self,
85 memory: &RefCell<Memory>,
86 ) -> Result<ValueContainer, DIFReferenceNotFoundError> {
87 Ok(match self {
88 DIFValueContainer::Reference(address) => ValueContainer::Reference(
89 memory
90 .borrow()
91 .get_reference(&address)
92 .ok_or(DIFReferenceNotFoundError)?
93 .clone(),
94 ),
95 DIFValueContainer::Value(v) => {
96 ValueContainer::Value(v.to_value(memory)?)
97 }
98 })
99 }
100}
101
102impl From<DIFValue> for DIFValueContainer {
103 fn from(value: DIFValue) -> Self {
104 DIFValueContainer::Value(value)
105 }
106}
107impl From<&DIFValue> for DIFValueContainer {
108 fn from(value: &DIFValue) -> Self {
109 DIFValueContainer::Value(value.clone())
110 }
111}
112impl From<PointerAddress> for DIFValueContainer {
113 fn from(ptr: PointerAddress) -> Self {
114 DIFValueContainer::Reference(ptr)
115 }
116}
117
118impl DIFValueContainer {
119 pub fn from_value_container(
120 value_container: &ValueContainer,
121 memory: &RefCell<Memory>,
122 ) -> Self {
123 match value_container {
124 ValueContainer::Reference(reference) => {
125 let address = reference.ensure_pointer_address(memory);
127 DIFValueContainer::Reference(address)
128 }
129 ValueContainer::Value(value) => {
130 DIFValueContainer::Value(DIFValue::from_value(value, memory))
131 }
132 }
133 }
134}
135
136impl DIFValue {
137 fn from_value(value: &Value, memory: &RefCell<Memory>) -> Self {
138 let core_value = &value.inner;
139
140 let dif_core_value = match core_value {
141 CoreValue::Type(ty) => todo!("#382 Type value not supported in DIF"),
142 CoreValue::Null => DIFValueRepresentation::Null,
143 CoreValue::Boolean(bool) => DIFValueRepresentation::Boolean(bool.0),
144 CoreValue::Integer(integer) => {
145 DIFValueRepresentation::String(integer.to_string())
147 }
148 CoreValue::TypedInteger(integer) => {
149 match integer {
150 TypedInteger::I8(i) => {
151 DIFValueRepresentation::Number(*i as f64)
152 }
153 TypedInteger::U8(u) => {
154 DIFValueRepresentation::Number(*u as f64)
155 }
156 TypedInteger::I16(i) => {
157 DIFValueRepresentation::Number(*i as f64)
158 }
159 TypedInteger::U16(u) => {
160 DIFValueRepresentation::Number(*u as f64)
161 }
162 TypedInteger::I32(i) => {
163 DIFValueRepresentation::Number(*i as f64)
164 }
165 TypedInteger::U32(u) => {
166 DIFValueRepresentation::Number(*u as f64)
167 }
168 TypedInteger::I64(i) => {
170 DIFValueRepresentation::String(i.to_string())
171 }
172 TypedInteger::U64(u) => {
173 DIFValueRepresentation::String(u.to_string())
174 }
175 TypedInteger::I128(i) => {
176 DIFValueRepresentation::String(i.to_string())
177 }
178 TypedInteger::U128(u) => {
179 DIFValueRepresentation::String(u.to_string())
180 }
181 TypedInteger::Big(i) => {
182 DIFValueRepresentation::String(i.to_string())
183 }
184 }
185 }
186 CoreValue::Decimal(decimal) => {
187 DIFValueRepresentation::String(decimal.to_string())
189 }
190 CoreValue::TypedDecimal(decimal) => match decimal {
191 TypedDecimal::F32(f) => {
192 DIFValueRepresentation::Number(f.0 as f64)
193 }
194 TypedDecimal::F64(f) => DIFValueRepresentation::Number(f.0),
195 TypedDecimal::Decimal(bd) => {
196 DIFValueRepresentation::String(bd.to_string())
197 }
198 },
199 CoreValue::Text(text) => {
200 DIFValueRepresentation::String(text.0.clone())
201 }
202 CoreValue::Endpoint(endpoint) => {
203 DIFValueRepresentation::String(endpoint.to_string())
204 }
205 CoreValue::List(list) => DIFValueRepresentation::Array(
206 list.iter()
207 .map(|v| DIFValueContainer::from_value_container(v, memory))
208 .collect(),
209 ),
210 CoreValue::Map(map) => DIFValueRepresentation::Map(
211 map.into_iter()
212 .map(|(k, v)| {
213 (
214 match k {
215 MapKey::Text(text_key) => {
216 DIFValueContainer::Value(
217 DIFValueRepresentation::String(
218 text_key.to_string(),
219 )
220 .into(),
221 )
222 }
223 _ => DIFValueContainer::from_value_container(
224 &ValueContainer::from(k),
225 memory,
226 ),
227 },
228 DIFValueContainer::from_value_container(v, memory),
229 )
230 })
231 .collect(),
232 ),
233 };
234
235 DIFValue {
236 value: dif_core_value,
237 r#type: get_type_if_non_default(&value.actual_type, memory),
238 }
239 }
240}
241
242fn get_type_if_non_default(
251 type_container: &TypeContainer,
252 memory: &RefCell<Memory>,
253) -> Option<DIFTypeContainer> {
254 match type_container {
255 TypeContainer::TypeReference(inner) => {
256 if let Some(Ok(address)) = inner
257 .borrow()
258 .pointer_address
259 .as_ref()
260 .map(CoreLibPointerId::try_from)
261 && matches!(
262 address,
263 CoreLibPointerId::Decimal(Some(DecimalTypeVariant::F64))
264 | CoreLibPointerId::Boolean
265 | CoreLibPointerId::Text
266 | CoreLibPointerId::List
267 | CoreLibPointerId::Map
268 | CoreLibPointerId::Null
269 )
270 {
271 None
272 } else {
273 Some(DIFTypeContainer::from_type_container(
274 type_container,
275 memory,
276 ))
277 }
278 }
279 _ => Some(DIFTypeContainer::from_type_container(
280 type_container,
281 memory,
282 )),
283 }
284}
285
286#[cfg(test)]
287mod tests {
288 use crate::dif::DIFConvertible;
289 use crate::runtime::memory::Memory;
290 use crate::values::core_values::endpoint::Endpoint;
291 use crate::values::core_values::map::Map;
292 use crate::values::value_container::ValueContainer;
293 use crate::{
294 dif::{r#type::DIFTypeContainer, value::DIFValue},
295 libs::core::CoreLibPointerId,
296 values::core_values::integer::typed_integer::IntegerTypeVariant,
297 };
298 use datex_core::values::value::Value;
299 use std::cell::RefCell;
300
301 fn get_mock_memory() -> RefCell<Memory> {
302 RefCell::new(Memory::new(Endpoint::default()))
303 }
304
305 #[test]
306 fn default_type() {
307 let memory = get_mock_memory();
308 let dif = DIFValue::from_value(&Value::from(true), &memory);
309 assert!(dif.r#type.is_none());
310
311 let dif = DIFValue::from_value(&Value::from("hello"), &memory);
312 assert!(dif.r#type.is_none());
313
314 let dif = DIFValue::from_value(&Value::null(), &memory);
315 assert!(dif.r#type.is_none());
316
317 let dif = DIFValue::from_value(&Value::from(3.5f64), &memory);
318 assert!(dif.r#type.is_none());
319
320 let dif = DIFValue::from_value(
321 &Value::from(vec![Value::from(1), Value::from(2), Value::from(3)]),
322 &memory,
323 );
324 assert!(dif.r#type.is_none());
325
326 let dif = DIFValue::from_value(
327 &Value::from(Map::from(vec![
328 ("a".to_string(), ValueContainer::from(1)),
329 ("b".to_string(), ValueContainer::from(2)),
330 ])),
331 &memory,
332 );
333 assert!(dif.r#type.is_none());
334 }
335
336 #[test]
337 fn non_default_type() {
338 let memory = get_mock_memory();
339 let dif = DIFValue::from_value(&Value::from(123u16), &memory);
340 assert!(dif.r#type.is_some());
341 if let DIFTypeContainer::Reference(reference) = dif.r#type.unwrap() {
342 assert_eq!(
343 reference,
344 CoreLibPointerId::Integer(Some(IntegerTypeVariant::U16)).into()
345 );
346 } else {
347 panic!("Expected reference type");
348 }
349
350 let dif = DIFValue::from_value(&Value::from(123i64), &memory);
351 assert!(dif.r#type.is_some());
352 if let DIFTypeContainer::Reference(reference) = dif.r#type.unwrap() {
353 assert_eq!(
354 reference,
355 CoreLibPointerId::Integer(Some(IntegerTypeVariant::I64)).into()
356 );
357 } else {
358 panic!("Expected reference type");
359 }
360 }
361
362 #[test]
363 fn serde_dif_value() {
364 let memory = get_mock_memory();
365 let dif = DIFValue::from_value(&Value::from("Hello, world!"), &memory);
366 let serialized = dif.as_json();
367 let deserialized = DIFValue::from_json(&serialized);
368 assert_eq!(dif, deserialized);
369 }
370}