it_json_serde/
ivalues_to_json.rs

1/*
2 * Copyright 2022 Fluence Labs Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use crate::IValue;
18use crate::IType;
19use crate::ITJsonSeDeError::Se;
20use crate::JsonResult;
21use crate::MRecordTypes;
22
23use serde_json::Value as JValue;
24
25pub fn ivalues_to_json(
26    mut ivalues: Vec<IValue>,
27    outputs: &[IType],
28    record_types: &MRecordTypes,
29) -> JsonResult<JValue> {
30    if outputs.len() != ivalues.len() {
31        return Err(Se(format!(
32            "resulted values {:?} and function signature {:?} aren't compatible",
33            ivalues, outputs
34        )));
35    }
36    match ivalues.len() {
37        0 => Ok(JValue::Null),
38        1 => ivalue_to_json(ivalues.remove(0), outputs.first().unwrap(), record_types),
39        _ => unimplemented!(
40            "multi-values aren't supported now - more then one result values aren't possible"
41        ),
42    }
43}
44
45fn ivalue_to_json(
46    ivalue: IValue,
47    output: &IType,
48    record_types: &MRecordTypes,
49) -> JsonResult<JValue> {
50    use serde_json::json;
51
52    // clone here needed because binding by-value and by-ref in the same pattern in unstable
53    match (ivalue, output.clone()) {
54        (IValue::Boolean(value), IType::Boolean) => Ok(json!(value)),
55        (IValue::S8(value), IType::S8) => Ok(json!(value)),
56        (IValue::S16(value), IType::S16) => Ok(json!(value)),
57        (IValue::S32(value), IType::S32) => Ok(json!(value)),
58        (IValue::S64(value), IType::S64) => Ok(json!(value)),
59        (IValue::U8(value), IType::U8) => Ok(json!(value)),
60        (IValue::U16(value), IType::U16) => Ok(json!(value)),
61        (IValue::U32(value), IType::U32) => Ok(json!(value)),
62        (IValue::U64(value), IType::U64) => Ok(json!(value)),
63        (IValue::I32(value), IType::I32) => Ok(json!(value)),
64        (IValue::I64(value), IType::I64) => Ok(json!(value)),
65        (IValue::F32(value), IType::F32) => Ok(json!(value)),
66        (IValue::F64(value), IType::F64) => Ok(json!(value)),
67        (IValue::String(value), IType::String) => Ok(json!(value)),
68        (IValue::ByteArray(value), IType::ByteArray) => {
69            let result = value.into_iter().map(|v| json!(v)).collect();
70            Ok(JValue::Array(result))
71        }
72        (IValue::Array(value), IType::ByteArray) => {
73            let result: JsonResult<Vec<_>> = value
74                .into_iter()
75                .map(|v| ivalue_to_json(v, &IType::U8, record_types))
76                .collect();
77
78            Ok(JValue::Array(result?))
79        }
80        (IValue::ByteArray(value), IType::Array(array_ty)) => {
81            let result: JsonResult<Vec<_>> = value
82                .into_iter()
83                .map(|v| ivalue_to_json(IValue::U8(v), &array_ty, record_types))
84                .collect();
85
86            Ok(JValue::Array(result?))
87        }
88        (IValue::Array(value), IType::Array(array_ty)) => {
89            let result: JsonResult<Vec<_>> = value
90                .into_iter()
91                .map(|v| ivalue_to_json(v, &array_ty, record_types))
92                .collect();
93
94            Ok(JValue::Array(result?))
95        }
96        (IValue::Record(field_values), IType::Record(record_id)) => {
97            let record_type = record_types.get(&record_id).ok_or_else(|| {
98                Se(format!(
99                    "record id {} wasn't found in module record types",
100                    record_id
101                ))
102            })?;
103            let field_types = &record_type.fields;
104
105            if field_values.len() != field_types.len() {
106                return Err(Se(format!(
107                    "output record {:?} isn't compatible to output record fields {:?}",
108                    field_values, field_types
109                )));
110            }
111
112            let field_values = field_values.into_vec();
113            let mut result = serde_json::Map::with_capacity(field_values.len());
114
115            for (field_value, field_type) in field_values.into_iter().zip(field_types.iter()) {
116                let json_field_value = ivalue_to_json(field_value, &field_type.ty, record_types)?;
117                result.insert(field_type.name.clone(), json_field_value);
118            }
119
120            Ok(JValue::Object(result))
121        }
122        (ivalue, itype) => Err(Se(format!(
123            "value {:?} is incompatible to type {:?}",
124            ivalue, itype
125        ))),
126    }
127}