multiversx_chain_scenario_format/value_interpreter/
interpreter.rs

1use crate::{interpret_trait::InterpreterContext, serde_raw::ValueSubTree};
2
3use super::{
4    file_loader::{load_file, MxscFileJson},
5    functions::*,
6    parse_num::*,
7    prefixes::*,
8};
9
10pub fn interpret_subtree(vst: &ValueSubTree, context: &InterpreterContext) -> Vec<u8> {
11    match vst {
12        ValueSubTree::Str(s) => interpret_string(s, context),
13        ValueSubTree::List(l) => {
14            let mut concat = Vec::<u8>::new();
15            for item in l.iter() {
16                concat.extend_from_slice(interpret_subtree(item, context).as_slice());
17            }
18            concat
19        }
20        ValueSubTree::Map(m) => {
21            let mut concat = Vec::<u8>::new();
22            for (_, value) in m.iter() {
23                concat.extend_from_slice(interpret_subtree(value, context).as_slice());
24            }
25            concat
26        }
27    }
28}
29
30pub fn interpret_string(s: &str, context: &InterpreterContext) -> Vec<u8> {
31    if s.is_empty() {
32        return Vec::new();
33    }
34
35    // concatenate values of different formats
36    let split_parts: Vec<_> = s.split('|').collect();
37    if split_parts.len() > 1 {
38        let mut result = Vec::<u8>::new();
39        for part in split_parts.iter() {
40            result.extend_from_slice(interpret_string(part, context).as_slice());
41        }
42        return result;
43    }
44
45    if s == "true" {
46        return [1u8].to_vec();
47    }
48
49    if s == "false" {
50        return Vec::new();
51    }
52
53    for str_prefix in STR_PREFIXES.iter() {
54        if let Some(stripped) = s.strip_prefix(str_prefix) {
55            return stripped.as_bytes().to_vec();
56        }
57    }
58
59    if let Some(stripped) = s.strip_prefix(ADDR_PREFIX) {
60        return address_expression(stripped);
61    }
62
63    if let Some(stripped) = s.strip_prefix(SC_ADDR_PREFIX) {
64        return sc_address_expression(stripped, &context.vm_type);
65    }
66
67    if let Some(stripped) = s.strip_prefix(FILE_PREFIX) {
68        return load_file(stripped, context, |c| c);
69    }
70
71    if let Some(stripped) = s.strip_prefix(MXSC_PREFIX) {
72        return load_file(stripped, context, |content| {
73            let mxsc_json: MxscFileJson = serde_json::from_slice(&content).unwrap();
74            hex::decode(mxsc_json.code).expect("Could not decode contract code")
75        });
76    }
77
78    if let Some(stripped) = s.strip_prefix(KECCAK256_PREFIX) {
79        let arg = interpret_string(stripped, context);
80        return keccak256(arg.as_slice());
81    }
82
83    if let Some(stripped) = s.strip_prefix(BECH32_PREFIX) {
84        return bech32(stripped);
85    }
86
87    if let Some(stripped) = s.strip_prefix(NESTED_PREFIX) {
88        return parse_nested(stripped, context);
89    }
90
91    if let Some(fixed_width) = try_parse_fixed_width(s) {
92        return fixed_width;
93    }
94
95    parse_num(s)
96}
97
98fn parse_nested(s: &str, context: &InterpreterContext) -> Vec<u8> {
99    let parsed = interpret_string(s, context);
100    let encoded_length = (parsed.len() as u32).to_be_bytes();
101    [&encoded_length[..], &parsed[..]].concat()
102}