1use crate::data::{to_decimal, to_non_fungible_local_id, to_precise_decimal};
2use crate::internal_prelude::*;
3use radix_common::data::manifest::model::{
4 ManifestBlobRef, ManifestBucket, ManifestExpression, ManifestProof,
5};
6use radix_common::data::manifest::{
7 ManifestCustomValue, ManifestCustomValueKind, ManifestValue, ManifestValueKind,
8};
9use radix_common::data::scrypto::model::{Own, Reference};
10use radix_common::data::scrypto::{
11 ScryptoCustomValue, ScryptoCustomValueKind, ScryptoValue, ScryptoValueKind,
12};
13use sbor::rust::vec::Vec;
14
15pub trait TransformHandler<E> {
16 fn replace_bucket(&mut self, b: ManifestBucket) -> Result<Own, E>;
17 fn replace_proof(&mut self, p: ManifestProof) -> Result<Own, E>;
18 fn replace_address_reservation(&mut self, p: ManifestAddressReservation) -> Result<Own, E>;
19 fn replace_named_address(&mut self, p: ManifestNamedAddress) -> Result<Reference, E>;
20 fn replace_expression(&mut self, e: ManifestExpression) -> Result<Vec<Own>, E>;
21 fn replace_blob(&mut self, b: ManifestBlobRef) -> Result<Vec<u8>, E>;
22}
23
24pub fn transform<T: TransformHandler<E>, E>(
25 value: ManifestValue,
26 handler: &mut T,
27) -> Result<ScryptoValue, E> {
28 match value {
29 sbor::Value::Bool { value } => Ok(ScryptoValue::Bool { value }),
30 sbor::Value::I8 { value } => Ok(ScryptoValue::I8 { value }),
31 sbor::Value::I16 { value } => Ok(ScryptoValue::I16 { value }),
32 sbor::Value::I32 { value } => Ok(ScryptoValue::I32 { value }),
33 sbor::Value::I64 { value } => Ok(ScryptoValue::I64 { value }),
34 sbor::Value::I128 { value } => Ok(ScryptoValue::I128 { value }),
35 sbor::Value::U8 { value } => Ok(ScryptoValue::U8 { value }),
36 sbor::Value::U16 { value } => Ok(ScryptoValue::U16 { value }),
37 sbor::Value::U32 { value } => Ok(ScryptoValue::U32 { value }),
38 sbor::Value::U64 { value } => Ok(ScryptoValue::U64 { value }),
39 sbor::Value::U128 { value } => Ok(ScryptoValue::U128 { value }),
40 sbor::Value::String { value } => Ok(ScryptoValue::String { value }),
41 sbor::Value::Enum {
42 discriminator,
43 fields,
44 } => {
45 let mut transformed_fields = Vec::new();
46 for field in fields {
47 transformed_fields.push(transform(field, handler)?);
48 }
49 Ok(ScryptoValue::Enum {
50 discriminator,
51 fields: transformed_fields,
52 })
53 }
54 sbor::Value::Array {
55 element_value_kind,
56 elements,
57 } => {
58 let mut transformed_elements = Vec::new();
59 for element in elements {
60 transformed_elements.push(transform(element, handler)?);
61 }
62 Ok(ScryptoValue::Array {
63 element_value_kind: transform_value_kind(element_value_kind),
64 elements: transformed_elements,
65 })
66 }
67 sbor::Value::Tuple { fields } => {
68 let mut transformed_fields = Vec::new();
69 for field in fields {
70 transformed_fields.push(transform(field, handler)?);
71 }
72 Ok(ScryptoValue::Tuple {
73 fields: transformed_fields,
74 })
75 }
76 sbor::Value::Map {
77 key_value_kind,
78 value_value_kind,
79 entries,
80 } => {
81 let mut transformed_entries = Vec::new();
82 for entry in entries {
83 transformed_entries
84 .push((transform(entry.0, handler)?, transform(entry.1, handler)?));
85 }
86 Ok(ScryptoValue::Map {
87 key_value_kind: transform_value_kind(key_value_kind),
88 value_value_kind: transform_value_kind(value_value_kind),
89 entries: transformed_entries,
90 })
91 }
92 sbor::Value::Custom { value } => match value {
93 ManifestCustomValue::Address(address) => match address {
94 ManifestAddress::Static(node_id) => Ok(ScryptoValue::Custom {
95 value: ScryptoCustomValue::Reference(Reference(node_id)),
96 }),
97 ManifestAddress::Named(name_id) => Ok(ScryptoValue::Custom {
98 value: ScryptoCustomValue::Reference(handler.replace_named_address(name_id)?),
99 }),
100 },
101 ManifestCustomValue::Bucket(b) => Ok(ScryptoValue::Custom {
102 value: ScryptoCustomValue::Own(handler.replace_bucket(b)?),
103 }),
104 ManifestCustomValue::Proof(p) => Ok(ScryptoValue::Custom {
105 value: ScryptoCustomValue::Own(handler.replace_proof(p)?),
106 }),
107 ManifestCustomValue::AddressReservation(p) => Ok(ScryptoValue::Custom {
108 value: ScryptoCustomValue::Own(handler.replace_address_reservation(p)?),
109 }),
110 ManifestCustomValue::Expression(e) => Ok(ScryptoValue::Array {
111 element_value_kind: ScryptoValueKind::Custom(ScryptoCustomValueKind::Own),
112 elements: handler
113 .replace_expression(e)?
114 .into_iter()
115 .map(|e| ScryptoValue::Custom {
116 value: ScryptoCustomValue::Own(e),
117 })
118 .collect(),
119 }),
120 ManifestCustomValue::Blob(b) => Ok(ScryptoValue::Array {
121 element_value_kind: ScryptoValueKind::U8,
122 elements: handler
123 .replace_blob(b)?
124 .into_iter()
125 .map(|e| ScryptoValue::U8 { value: e })
126 .collect(),
127 }),
128 ManifestCustomValue::Decimal(d) => Ok(ScryptoValue::Custom {
129 value: ScryptoCustomValue::Decimal(to_decimal(d)),
130 }),
131 ManifestCustomValue::PreciseDecimal(d) => Ok(ScryptoValue::Custom {
132 value: ScryptoCustomValue::PreciseDecimal(to_precise_decimal(d)),
133 }),
134 ManifestCustomValue::NonFungibleLocalId(id) => Ok(ScryptoValue::Custom {
135 value: ScryptoCustomValue::NonFungibleLocalId(to_non_fungible_local_id(id)),
136 }),
137 },
138 }
139}
140
141pub fn transform_value_kind(kind: ManifestValueKind) -> ScryptoValueKind {
142 match kind {
143 sbor::ValueKind::Bool => ScryptoValueKind::Bool,
144 sbor::ValueKind::I8 => ScryptoValueKind::I8,
145 sbor::ValueKind::I16 => ScryptoValueKind::I16,
146 sbor::ValueKind::I32 => ScryptoValueKind::I32,
147 sbor::ValueKind::I64 => ScryptoValueKind::I64,
148 sbor::ValueKind::I128 => ScryptoValueKind::I128,
149 sbor::ValueKind::U8 => ScryptoValueKind::U8,
150 sbor::ValueKind::U16 => ScryptoValueKind::U16,
151 sbor::ValueKind::U32 => ScryptoValueKind::U32,
152 sbor::ValueKind::U64 => ScryptoValueKind::U64,
153 sbor::ValueKind::U128 => ScryptoValueKind::U128,
154 sbor::ValueKind::String => ScryptoValueKind::String,
155 sbor::ValueKind::Enum => ScryptoValueKind::Enum,
156 sbor::ValueKind::Array => ScryptoValueKind::Array,
157 sbor::ValueKind::Tuple => ScryptoValueKind::Tuple,
158 sbor::ValueKind::Map => ScryptoValueKind::Map,
159 sbor::ValueKind::Custom(c) => match c {
160 ManifestCustomValueKind::Address => {
161 ScryptoValueKind::Custom(ScryptoCustomValueKind::Reference)
162 }
163 ManifestCustomValueKind::Bucket => {
164 ScryptoValueKind::Custom(ScryptoCustomValueKind::Own)
165 }
166 ManifestCustomValueKind::Proof => ScryptoValueKind::Custom(ScryptoCustomValueKind::Own),
167 ManifestCustomValueKind::Expression => ScryptoValueKind::Array,
168 ManifestCustomValueKind::Blob => ScryptoValueKind::Array,
169 ManifestCustomValueKind::Decimal => {
170 ScryptoValueKind::Custom(ScryptoCustomValueKind::Decimal)
171 }
172 ManifestCustomValueKind::PreciseDecimal => {
173 ScryptoValueKind::Custom(ScryptoCustomValueKind::PreciseDecimal)
174 }
175 ManifestCustomValueKind::NonFungibleLocalId => {
176 ScryptoValueKind::Custom(ScryptoCustomValueKind::NonFungibleLocalId)
177 }
178 ManifestCustomValueKind::AddressReservation => {
179 ScryptoValueKind::Custom(ScryptoCustomValueKind::Own)
180 }
181 },
182 }
183}