1#[macro_export]
6macro_rules! i {
7 ($x:expr) => {
8 $x.try_into().expect("Parse Error")
9 };
10}
11
12#[macro_export]
14macro_rules! well_known_scrypto_custom_type {
15 ($t:ty, $value_kind:expr, $schema_type:expr, $size:expr, $well_known_type:ident, $well_known_type_data_method:ident$(,)?) => {
17 impl sbor::Categorize<$crate::data::scrypto::ScryptoCustomValueKind> for $t {
18 #[inline]
19 fn value_kind() -> sbor::ValueKind<$crate::data::scrypto::ScryptoCustomValueKind> {
20 sbor::ValueKind::Custom($value_kind)
21 }
22 }
23
24 impl<E: sbor::Encoder<$crate::data::scrypto::ScryptoCustomValueKind>>
25 sbor::Encode<$crate::data::scrypto::ScryptoCustomValueKind, E> for $t
26 {
27 #[inline]
28 fn encode_value_kind(&self, encoder: &mut E) -> Result<(), sbor::EncodeError> {
29 encoder.write_value_kind(Self::value_kind())
30 }
31
32 #[inline]
33 fn encode_body(&self, encoder: &mut E) -> Result<(), sbor::EncodeError> {
34 encoder.write_slice(&self.to_vec())
35 }
36 }
37
38 impl<D: sbor::Decoder<$crate::data::scrypto::ScryptoCustomValueKind>>
39 sbor::Decode<$crate::data::scrypto::ScryptoCustomValueKind, D> for $t
40 {
41 fn decode_body_with_value_kind(
42 decoder: &mut D,
43 value_kind: sbor::ValueKind<$crate::data::scrypto::ScryptoCustomValueKind>,
44 ) -> Result<Self, sbor::DecodeError> {
45 decoder.check_preloaded_value_kind(value_kind, Self::value_kind())?;
46 let slice = decoder.read_slice($size)?;
47 Self::try_from(slice).map_err(|_| sbor::DecodeError::InvalidCustomValue)
48 }
49 }
50
51 impl sbor::Describe<$crate::data::scrypto::ScryptoCustomTypeKind> for $t {
52 const TYPE_ID: sbor::RustTypeId = sbor::RustTypeId::WellKnown(
53 $crate::data::scrypto::well_known_scrypto_custom_types::$well_known_type,
54 );
55
56 fn type_data() -> sbor::TypeData<$crate::data::scrypto::ScryptoCustomTypeKind, sbor::RustTypeId> {
57 $crate::data::scrypto::well_known_scrypto_custom_types::$well_known_type_data_method()
58 }
59 }
60 };
61}
62
63#[macro_export]
64macro_rules! manifest_type {
65 ($t:ty, $value_kind:expr, $size: expr$(,)?) => {
67 impl sbor::Categorize<$crate::data::manifest::ManifestCustomValueKind> for $t {
68 #[inline]
69 fn value_kind() -> sbor::ValueKind<$crate::data::manifest::ManifestCustomValueKind> {
70 sbor::ValueKind::Custom($value_kind)
71 }
72 }
73
74 impl<E: sbor::Encoder<$crate::data::manifest::ManifestCustomValueKind>>
75 sbor::Encode<$crate::data::manifest::ManifestCustomValueKind, E> for $t
76 {
77 #[inline]
78 fn encode_value_kind(&self, encoder: &mut E) -> Result<(), sbor::EncodeError> {
79 encoder.write_value_kind(Self::value_kind())
80 }
81
82 #[inline]
83 fn encode_body(&self, encoder: &mut E) -> Result<(), sbor::EncodeError> {
84 encoder.write_slice(&self.to_vec())
85 }
86 }
87
88 impl<D: sbor::Decoder<$crate::data::manifest::ManifestCustomValueKind>>
89 sbor::Decode<$crate::data::manifest::ManifestCustomValueKind, D> for $t
90 {
91 fn decode_body_with_value_kind(
92 decoder: &mut D,
93 value_kind: sbor::ValueKind<$crate::data::manifest::ManifestCustomValueKind>,
94 ) -> Result<Self, sbor::DecodeError> {
95 decoder.check_preloaded_value_kind(value_kind, Self::value_kind())?;
96 let slice = decoder.read_slice($size)?;
97 Self::try_from(slice).map_err(|_| sbor::DecodeError::InvalidCustomValue)
98 }
99 }
100 };
101}
102
103#[macro_export]
104macro_rules! scrypto_describe_for_manifest_type {
105 ($t:ty, $well_known_type:ident, $well_known_type_data_method:ident$(,)?) => {
106 impl sbor::Describe<$crate::data::scrypto::ScryptoCustomTypeKind> for $t {
107 const TYPE_ID: sbor::RustTypeId = sbor::RustTypeId::WellKnown(
108 $crate::data::scrypto::well_known_scrypto_custom_types::$well_known_type,
109 );
110
111 fn type_data() -> sbor::TypeData<$crate::data::scrypto::ScryptoCustomTypeKind, sbor::RustTypeId> {
112 $crate::data::scrypto::well_known_scrypto_custom_types::$well_known_type_data_method()
113 }
114 }
115 }
116}
117
118#[macro_export]
119macro_rules! count {
120 () => {0usize};
121 ($a:expr) => {1usize};
122 ($a:expr, $($rest:expr),*) => {1usize + $crate::count!($($rest),*)};
123}
124
125#[macro_export]
126macro_rules! scrypto_args {
127 ($($args: expr),*) => {{
128 use sbor::Encoder;
129 let mut buf = sbor::rust::vec::Vec::new();
130 let mut encoder = $crate::data::scrypto::ScryptoEncoder::new(
131 &mut buf,
132 $crate::data::scrypto::SCRYPTO_SBOR_V1_MAX_DEPTH,
133 );
134 encoder
135 .write_payload_prefix($crate::data::scrypto::SCRYPTO_SBOR_V1_PAYLOAD_PREFIX)
136 .unwrap();
137 encoder
138 .write_value_kind($crate::data::scrypto::ScryptoValueKind::Tuple)
139 .unwrap();
140 encoder.write_size($crate::count!($(stringify!($args)),*)).unwrap();
142 $(
143 let arg = $args;
144 encoder.encode(&arg).unwrap();
145 )*
146 buf
147 }};
148}
149
150#[macro_export]
151macro_rules! manifest_args {
152 ($($args: expr),*$(,)?) => {{
153 use sbor::Encoder;
154 let mut buf = sbor::rust::vec::Vec::new();
155 let mut encoder = $crate::data::manifest::ManifestEncoder::new(&mut buf, $crate::data::manifest::MANIFEST_SBOR_V1_MAX_DEPTH);
156 encoder.write_payload_prefix($crate::data::manifest::MANIFEST_SBOR_V1_PAYLOAD_PREFIX).unwrap();
157 encoder.write_value_kind($crate::data::manifest::ManifestValueKind::Tuple).unwrap();
158 encoder.write_size($crate::count!($(stringify!($args)),*)).unwrap();
160 $(
161 let arg = $args;
162 encoder.encode(&arg).unwrap();
163 )*
164 let value = $crate::data::manifest::manifest_decode(&buf).unwrap();
165 ManifestArgs::new_from_tuple_or_panic(value)
166 }};
167}
168
169#[macro_export]
170macro_rules! to_manifest_value_and_unwrap {
171 ( $value:expr ) => {{
172 $crate::data::manifest::to_manifest_value($value).unwrap()
173 }};
174}
175
176#[macro_export]
200macro_rules! define_untyped_manifest_type_wrapper {
201 (
202 $scrypto_ty: ty => $manifest_ty_ident: ident ($inner_ty: ty)
203 ) => {
204 #[cfg_attr(
205 feature = "fuzzing",
206 derive(::arbitrary::Arbitrary, ::serde::Serialize, ::serde::Deserialize)
207 )]
208 #[derive(
209 Debug,
210 Clone,
211 PartialEq,
212 Eq,
213 $crate::prelude::ManifestEncode,
214 $crate::prelude::ManifestCategorize,
215 )]
216 #[sbor(transparent)]
217 pub struct $manifest_ty_ident($inner_ty);
218
219 const _: () = {
220 impl $manifest_ty_ident {
221 pub fn new(
222 value: impl Into<$scrypto_ty>,
223 ) -> Result<Self, $crate::prelude::ConversionError> {
224 let value = Into::<$scrypto_ty>::into(value);
225 let encoded_scrypto_bytes = $crate::prelude::scrypto_encode(&value)
226 .map_err($crate::prelude::ConversionError::EncodeError)?;
227 let scrypto_value = $crate::prelude::scrypto_decode::<
228 $crate::prelude::ScryptoValue,
229 >(&encoded_scrypto_bytes)
230 .map_err($crate::prelude::ConversionError::DecodeError)?;
231
232 let manifest_value =
233 $crate::prelude::scrypto_value_to_manifest_value(scrypto_value)?;
234 let encoded_manifest_bytes = $crate::prelude::manifest_encode(&manifest_value)
235 .map_err($crate::prelude::ConversionError::EncodeError)?;
236 $crate::prelude::manifest_decode(&encoded_manifest_bytes)
237 .map(Self)
238 .map_err($crate::prelude::ConversionError::DecodeError)
239 }
240
241 pub fn try_into_typed(
242 self,
243 ) -> Result<$scrypto_ty, $crate::prelude::ConversionError> {
244 let value = self.0;
245 let encoded_manifest_bytes = $crate::prelude::manifest_encode(&value)
246 .map_err($crate::prelude::ConversionError::EncodeError)?;
247 let manifest_value = $crate::prelude::manifest_decode::<
248 $crate::prelude::ManifestValue,
249 >(&encoded_manifest_bytes)
250 .map_err($crate::prelude::ConversionError::DecodeError)?;
251
252 let scrypto_value =
253 $crate::prelude::manifest_value_to_scrypto_value(manifest_value)?;
254 let encoded_scrypto_bytes = $crate::prelude::scrypto_encode(&scrypto_value)
255 .map_err($crate::prelude::ConversionError::EncodeError)?;
256 $crate::prelude::scrypto_decode::<$scrypto_ty>(&encoded_scrypto_bytes)
257 .map_err($crate::prelude::ConversionError::DecodeError)
258 }
259 }
260
261 impl<T> From<T> for $manifest_ty_ident
263 where
264 T: Into<$scrypto_ty>,
265 {
266 fn from(value: T) -> Self {
267 Self::new(value).expect(concat!(
268 "Conversion from ",
269 stringify!($scrypto_ty),
270 " into ",
271 stringify!($manifest_ty_ident),
272 " failed despite not being expected to fail"
273 ))
274 }
275 }
276
277 impl TryFrom<$manifest_ty_ident> for $scrypto_ty {
278 type Error = $crate::prelude::ConversionError;
279
280 fn try_from(value: $manifest_ty_ident) -> Result<Self, Self::Error> {
281 value.try_into_typed()
282 }
283 }
284
285 impl $crate::prelude::Describe<$crate::prelude::ScryptoCustomTypeKind>
286 for $manifest_ty_ident
287 {
288 const TYPE_ID: $crate::prelude::RustTypeId =
289 <$scrypto_ty as $crate::prelude::Describe<
290 $crate::prelude::ScryptoCustomTypeKind,
291 >>::TYPE_ID;
292
293 fn type_data() -> $crate::prelude::TypeData<
294 $crate::prelude::ScryptoCustomTypeKind,
295 $crate::prelude::RustTypeId,
296 > {
297 <$scrypto_ty as Describe<$crate::prelude::ScryptoCustomTypeKind>>::type_data()
298 }
299
300 fn add_all_dependencies(
301 aggregator: &mut $crate::prelude::TypeAggregator<$crate::prelude::ScryptoCustomTypeKind>
302 ) {
303 <$scrypto_ty as Describe<$crate::prelude::ScryptoCustomTypeKind>>::add_all_dependencies(aggregator)
304 }
305 }
306
307 impl<D: $crate::prelude::Decoder<$crate::prelude::ManifestCustomValueKind>> $crate::prelude::Decode<$crate::prelude::ManifestCustomValueKind, D> for $manifest_ty_ident
315 {
316 #[inline]
317 fn decode_body_with_value_kind(
318 decoder: &mut D,
319 value_kind: $crate::prelude::ValueKind<$crate::prelude::ManifestCustomValueKind>,
320 ) -> Result<Self, $crate::prelude::DecodeError> {
321 ::lazy_static::lazy_static! {
324 static ref SCHEMA: ($crate::prelude::LocalTypeId, $crate::prelude::VersionedSchema<$crate::prelude::ScryptoCustomSchema>) = $crate::prelude::generate_full_schema_from_single_type::<
325 $scrypto_ty,
326 $crate::prelude::ScryptoCustomSchema
327 >();
328 }
329
330 let inner_value = <$inner_ty
332 as $crate::prelude::Decode<$crate::prelude::ManifestCustomValueKind, D>
333 >::decode_body_with_value_kind(decoder, value_kind)?;
334
335 let encoded = $crate::prelude::manifest_encode(&inner_value).map_err(|_| $crate::prelude::DecodeError::InvalidCustomValue)?;
337 $crate::prelude::validate_payload_against_schema::<$crate::prelude::ManifestCustomExtension, _>(
338 &encoded,
339 SCHEMA.1.v1(),
340 SCHEMA.0,
341 &(),
342 $crate::prelude::MANIFEST_SBOR_V1_MAX_DEPTH
343 )
344 .map_err(|_| $crate::prelude::DecodeError::InvalidCustomValue)?;
345
346 Ok(Self(inner_value))
348 }
349 }
350 };
351 };
352}
353
354#[cfg(test)]
355mod test {
356 use crate::prelude::*;
357
358 #[test]
359 fn decoding_into_opaque_value_with_incorrect_schema_fails() {
360 #[derive(ScryptoSbor)]
362 pub enum MyEnum {
363 Variant(u32),
364 }
365
366 #[derive(ScryptoSbor, ManifestSbor)]
367 pub enum MyOtherEnum {
368 Variant(Decimal),
369 }
370
371 define_untyped_manifest_type_wrapper!(
372 MyEnum => ManifestMyEnum(EnumVariantValue<ManifestCustomValueKind, ManifestCustomValue>)
373 );
374
375 let encoded = manifest_encode(&MyOtherEnum::Variant(Decimal::ONE)).unwrap();
376
377 let decoded = manifest_decode::<ManifestMyEnum>(&encoded);
379
380 assert_eq!(decoded, Err(DecodeError::InvalidCustomValue))
382 }
383}