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