1use core::cmp::{min, Ordering};
2
3use crate::{
4 budget::{AsBudget, Budget, DepthLimiter},
5 host_object::{HostObject, MuxedScAddress},
6 storage::Storage,
7 xdr::{
8 AccountId, ContractCostType, ContractDataDurability, ContractExecutable,
9 CreateContractArgs, CreateContractArgsV2, Duration, Hash, Int128Parts, Int256Parts,
10 LedgerKey, LedgerKeyAccount, LedgerKeyContractCode, LedgerKeyContractData,
11 LedgerKeyTrustLine, PublicKey, ScAddress, ScContractInstance, ScError, ScErrorCode,
12 ScErrorType, ScMap, ScMapEntry, ScNonceKey, ScVal, ScVec, TimePoint, TrustLineAsset,
13 UInt128Parts, UInt256Parts, Uint256,
14 },
15 Compare, Host, HostError, SymbolStr, I256, U256,
16};
17
18use super::declared_size::DeclaredSizeForMetering;
19
20fn host_obj_discriminant(ho: &HostObject) -> usize {
27 match ho {
28 HostObject::U64(_) => 0,
29 HostObject::I64(_) => 1,
30 HostObject::TimePoint(_) => 2,
31 HostObject::Duration(_) => 3,
32 HostObject::U128(_) => 4,
33 HostObject::I128(_) => 5,
34 HostObject::U256(_) => 6,
35 HostObject::I256(_) => 7,
36 HostObject::Bytes(_) => 8,
37 HostObject::String(_) => 9,
38 HostObject::Symbol(_) => 10,
39 HostObject::Vec(_) => 11,
40 HostObject::Map(_) => 12,
41 HostObject::Address(_) => 13,
42 HostObject::MuxedAddress(_) => 14,
43 }
44}
45
46impl Compare<HostObject> for Host {
47 type Error = HostError;
48
49 fn compare(&self, a: &HostObject, b: &HostObject) -> Result<Ordering, Self::Error> {
50 use HostObject::*;
51 let _span = tracy_span!("Compare<HostObject>");
52 self.budget_cloned().with_limited_depth(|_| {
54 match (a, b) {
55 (U64(a), U64(b)) => self.as_budget().compare(a, b),
56 (I64(a), I64(b)) => self.as_budget().compare(a, b),
57 (TimePoint(a), TimePoint(b)) => self.as_budget().compare(a, b),
58 (Duration(a), Duration(b)) => self.as_budget().compare(a, b),
59 (U128(a), U128(b)) => self.as_budget().compare(a, b),
60 (I128(a), I128(b)) => self.as_budget().compare(a, b),
61 (U256(a), U256(b)) => self.as_budget().compare(a, b),
62 (I256(a), I256(b)) => self.as_budget().compare(a, b),
63 (Vec(a), Vec(b)) => self.compare(a, b),
64 (Map(a), Map(b)) => self.compare(a, b),
65 (Bytes(a), Bytes(b)) => self.as_budget().compare(&a.as_slice(), &b.as_slice()),
66 (String(a), String(b)) => self.as_budget().compare(&a.as_slice(), &b.as_slice()),
67 (Symbol(a), Symbol(b)) => self.as_budget().compare(&a.as_slice(), &b.as_slice()),
68 (Address(a), Address(b)) => self.as_budget().compare(a, b),
69 (MuxedAddress(a), MuxedAddress(b)) => self.as_budget().compare(a, b),
70
71 (U64(_), _)
75 | (TimePoint(_), _)
76 | (Duration(_), _)
77 | (I64(_), _)
78 | (U128(_), _)
79 | (I128(_), _)
80 | (U256(_), _)
81 | (I256(_), _)
82 | (Vec(_), _)
83 | (Map(_), _)
84 | (Bytes(_), _)
85 | (String(_), _)
86 | (Symbol(_), _)
87 | (Address(_), _)
88 | (MuxedAddress(_), _) => {
89 let a = host_obj_discriminant(a);
90 let b = host_obj_discriminant(b);
91 Ok(a.cmp(&b))
92 }
93 }
94 })
95 }
96}
97
98impl Compare<&[u8]> for Budget {
99 type Error = HostError;
100
101 fn compare(&self, a: &&[u8], b: &&[u8]) -> Result<Ordering, Self::Error> {
102 self.charge(ContractCostType::MemCmp, Some(min(a.len(), b.len()) as u64))?;
103 Ok(a.cmp(b))
104 }
105}
106
107impl<const N: usize> Compare<[u8; N]> for Budget {
108 type Error = HostError;
109
110 fn compare(&self, a: &[u8; N], b: &[u8; N]) -> Result<Ordering, Self::Error> {
111 self.charge(ContractCostType::MemCmp, Some(min(a.len(), b.len()) as u64))?;
112 Ok(a.cmp(b))
113 }
114}
115
116struct FixedSizeOrdType<'a, T: Ord + DeclaredSizeForMetering>(&'a T);
126impl<T: Ord + DeclaredSizeForMetering> Compare<FixedSizeOrdType<'_, T>> for Budget {
127 type Error = HostError;
128 fn compare(
129 &self,
130 a: &FixedSizeOrdType<'_, T>,
131 b: &FixedSizeOrdType<'_, T>,
132 ) -> Result<Ordering, Self::Error> {
133 debug_assert!(
136 std::mem::size_of::<T>() as u64 <= <T as DeclaredSizeForMetering>::DECLARED_SIZE,
137 "{}: mem size: {}, declared: {}",
138 std::any::type_name::<T>(),
139 std::mem::size_of::<T>(),
140 <T as DeclaredSizeForMetering>::DECLARED_SIZE
141 );
142 self.charge(
143 ContractCostType::MemCmp,
144 Some(<T as DeclaredSizeForMetering>::DECLARED_SIZE),
145 )?;
146 Ok(a.0.cmp(b.0))
147 }
148}
149
150macro_rules! impl_compare_fixed_size_ord_type {
151 ($t:ty) => {
152 impl Compare<$t> for Budget {
153 type Error = HostError;
154 fn compare(&self, a: &$t, b: &$t) -> Result<Ordering, Self::Error> {
155 self.compare(&FixedSizeOrdType(a), &FixedSizeOrdType(b))
156 }
157 }
158 impl Compare<$t> for Host {
159 type Error = HostError;
160 fn compare(&self, a: &$t, b: &$t) -> Result<Ordering, Self::Error> {
161 self.as_budget().compare(a, b)
162 }
163 }
164 };
165}
166
167impl_compare_fixed_size_ord_type!(bool);
168impl_compare_fixed_size_ord_type!(u32);
169impl_compare_fixed_size_ord_type!(i32);
170impl_compare_fixed_size_ord_type!(u64);
171impl_compare_fixed_size_ord_type!(i64);
172impl_compare_fixed_size_ord_type!(u128);
173impl_compare_fixed_size_ord_type!(i128);
174
175impl_compare_fixed_size_ord_type!(U256);
176impl_compare_fixed_size_ord_type!(I256);
177impl_compare_fixed_size_ord_type!(Int128Parts);
178impl_compare_fixed_size_ord_type!(UInt128Parts);
179impl_compare_fixed_size_ord_type!(Int256Parts);
180impl_compare_fixed_size_ord_type!(UInt256Parts);
181impl_compare_fixed_size_ord_type!(TimePoint);
182impl_compare_fixed_size_ord_type!(Duration);
183impl_compare_fixed_size_ord_type!(Hash);
184impl_compare_fixed_size_ord_type!(Uint256);
185impl_compare_fixed_size_ord_type!(ContractExecutable);
186impl_compare_fixed_size_ord_type!(AccountId);
187impl_compare_fixed_size_ord_type!(ScError);
188impl_compare_fixed_size_ord_type!(ScAddress);
189impl_compare_fixed_size_ord_type!(MuxedScAddress);
190impl_compare_fixed_size_ord_type!(ScNonceKey);
191impl_compare_fixed_size_ord_type!(PublicKey);
192impl_compare_fixed_size_ord_type!(TrustLineAsset);
193impl_compare_fixed_size_ord_type!(ContractDataDurability);
194impl_compare_fixed_size_ord_type!(CreateContractArgs);
195impl_compare_fixed_size_ord_type!(CreateContractArgsV2);
196
197impl_compare_fixed_size_ord_type!(LedgerKeyAccount);
198impl_compare_fixed_size_ord_type!(LedgerKeyTrustLine);
199impl_compare_fixed_size_ord_type!(LedgerKeyContractCode);
201
202impl Compare<SymbolStr> for Budget {
203 type Error = HostError;
204
205 fn compare(&self, a: &SymbolStr, b: &SymbolStr) -> Result<Ordering, Self::Error> {
206 self.compare(
207 &<SymbolStr as AsRef<[u8]>>::as_ref(a),
208 &<SymbolStr as AsRef<[u8]>>::as_ref(b),
209 )
210 }
211}
212
213impl Compare<ScVec> for Budget {
214 type Error = HostError;
215
216 fn compare(&self, a: &ScVec, b: &ScVec) -> Result<Ordering, Self::Error> {
217 let a: &Vec<ScVal> = a;
218 let b: &Vec<ScVal> = b;
219 self.compare(a, b)
220 }
221}
222
223impl Compare<ScMap> for Budget {
224 type Error = HostError;
225
226 fn compare(&self, a: &ScMap, b: &ScMap) -> Result<Ordering, Self::Error> {
227 let a: &Vec<ScMapEntry> = a;
228 let b: &Vec<ScMapEntry> = b;
229 self.compare(a, b)
230 }
231}
232
233impl Compare<ScMapEntry> for Budget {
234 type Error = HostError;
235
236 fn compare(&self, a: &ScMapEntry, b: &ScMapEntry) -> Result<Ordering, Self::Error> {
237 match self.compare(&a.key, &b.key)? {
238 Ordering::Equal => self.compare(&a.val, &b.val),
239 cmp => Ok(cmp),
240 }
241 }
242}
243
244impl Compare<ScVal> for Budget {
245 type Error = HostError;
246
247 fn compare(&self, a: &ScVal, b: &ScVal) -> Result<Ordering, Self::Error> {
248 use ScVal::*;
249 self.clone().with_limited_depth(|_| match (a, b) {
251 (Vec(Some(a)), Vec(Some(b))) => self.compare(a, b),
252 (Map(Some(a)), Map(Some(b))) => self.compare(a, b),
253
254 (Vec(None), _) | (_, Vec(None)) | (Map(None), _) | (_, Map(None)) => {
255 Err((ScErrorType::Value, ScErrorCode::InvalidInput).into())
256 }
257
258 (Bytes(a), Bytes(b)) => {
259 <Self as Compare<&[u8]>>::compare(self, &a.as_slice(), &b.as_slice())
260 }
261
262 (String(a), String(b)) => {
263 <Self as Compare<&[u8]>>::compare(self, &a.as_slice(), &b.as_slice())
264 }
265
266 (Symbol(a), Symbol(b)) => {
267 <Self as Compare<&[u8]>>::compare(self, &a.as_slice(), &b.as_slice())
268 }
269
270 (ContractInstance(a), ContractInstance(b)) => self.compare(&a, &b),
271
272 (Void, Void) => Ok(Ordering::Equal),
274 (LedgerKeyContractInstance, LedgerKeyContractInstance) => Ok(Ordering::Equal),
275
276 (Bool(a), Bool(b)) => self.compare(&a, &b),
278 (Error(a), Error(b)) => self.compare(&a, &b),
279 (U32(a), U32(b)) => self.compare(&a, &b),
280 (I32(a), I32(b)) => self.compare(&a, &b),
281 (U64(a), U64(b)) => self.compare(&a, &b),
282 (I64(a), I64(b)) => self.compare(&a, &b),
283 (Timepoint(a), Timepoint(b)) => self.compare(&a, &b),
284 (Duration(a), Duration(b)) => self.compare(&a, &b),
285 (U128(a), U128(b)) => self.compare(&a, &b),
286 (I128(a), I128(b)) => self.compare(&a, &b),
287 (U256(a), U256(b)) => self.compare(&a, &b),
288 (I256(a), I256(b)) => self.compare(&a, &b),
289 (Address(a), Address(b)) => self.compare(&a, &b),
290 (LedgerKeyNonce(a), LedgerKeyNonce(b)) => self.compare(&a, &b),
291
292 (Vec(_), _)
296 | (Map(_), _)
297 | (Bytes(_), _)
298 | (String(_), _)
299 | (Symbol(_), _)
300 | (ContractInstance(_), _)
301 | (Bool(_), _)
302 | (Void, _)
303 | (Error(_), _)
304 | (U32(_), _)
305 | (I32(_), _)
306 | (U64(_), _)
307 | (I64(_), _)
308 | (Timepoint(_), _)
309 | (Duration(_), _)
310 | (U128(_), _)
311 | (I128(_), _)
312 | (U256(_), _)
313 | (I256(_), _)
314 | (Address(_), _)
315 | (LedgerKeyContractInstance, _)
316 | (LedgerKeyNonce(_), _) => Ok(a.discriminant().cmp(&b.discriminant())),
317 })
318 }
319}
320
321impl Compare<ScContractInstance> for Budget {
322 type Error = HostError;
323
324 fn compare(
325 &self,
326 a: &ScContractInstance,
327 b: &ScContractInstance,
328 ) -> Result<Ordering, Self::Error> {
329 self.compare(&(&a.executable, &a.storage), &(&b.executable, &b.storage))
330 }
331}
332
333impl Compare<LedgerKeyContractData> for Budget {
334 type Error = HostError;
335
336 fn compare(
337 &self,
338 a: &LedgerKeyContractData,
339 b: &LedgerKeyContractData,
340 ) -> Result<Ordering, Self::Error> {
341 self.compare(
342 &(&a.contract, &a.key, &a.durability),
343 &(&b.contract, &b.key, &b.durability),
344 )
345 }
346}
347
348impl Compare<LedgerKey> for Budget {
349 type Error = HostError;
350
351 fn compare(&self, a: &LedgerKey, b: &LedgerKey) -> Result<Ordering, Self::Error> {
352 Storage::check_supported_ledger_key_type(a)?;
353 Storage::check_supported_ledger_key_type(b)?;
354 use LedgerKey::*;
355 match (a, b) {
356 (Account(a), Account(b)) => self.compare(&a, &b),
357 (Trustline(a), Trustline(b)) => self.compare(&a, &b),
358 (ContractData(a), ContractData(b)) => self.compare(&a, &b),
359 (ContractCode(a), ContractCode(b)) => self.compare(&a, &b),
360
361 (Offer(_), _)
363 | (Data(_), _)
364 | (ClaimableBalance(_), _)
365 | (LiquidityPool(_), _)
366 | (ConfigSetting(_), _)
367 | (Ttl(_), _)
368 | (_, Offer(_))
369 | (_, Data(_))
370 | (_, ClaimableBalance(_))
371 | (_, LiquidityPool(_))
372 | (_, ConfigSetting(_))
373 | (_, Ttl(_)) => Err((ScErrorType::Value, ScErrorCode::InternalError).into()),
374
375 (Account(_), _) | (Trustline(_), _) | (ContractData(_), _) | (ContractCode(_), _) => {
379 Ok(a.discriminant().cmp(&b.discriminant()))
380 }
381 }
382 }
383}
384
385#[cfg(test)]
386mod tests {
387 use super::*;
388 use crate::xdr::ScVal;
389 use crate::{Compare, Host, Tag, TryFromVal, Val};
390 use itertools::Itertools;
391
392 #[test]
393 fn test_scvec_unequal_lengths() {
394 {
395 let v1 = ScVec::try_from((0, 1)).unwrap();
396 let v2 = ScVec::try_from((0, 1, 2)).unwrap();
397 let expected_cmp = Ordering::Less;
398 let budget = Budget::default();
399 let actual_cmp = budget.compare(&v1, &v2).unwrap();
400 assert_eq!(expected_cmp, actual_cmp);
401 }
402 {
403 let v1 = ScVec::try_from((0, 1, 2)).unwrap();
404 let v2 = ScVec::try_from((0, 1)).unwrap();
405 let expected_cmp = Ordering::Greater;
406 let budget = Budget::default();
407 let actual_cmp = budget.compare(&v1, &v2).unwrap();
408 assert_eq!(expected_cmp, actual_cmp);
409 }
410 {
411 let v1 = ScVec::try_from((0, 1)).unwrap();
412 let v2 = ScVec::try_from((0, 0, 2)).unwrap();
413 let expected_cmp = Ordering::Greater;
414 let budget = Budget::default();
415 let actual_cmp = budget.compare(&v1, &v2).unwrap();
416 assert_eq!(expected_cmp, actual_cmp);
417 }
418 {
419 let v1 = ScVec::try_from((0, 0, 2)).unwrap();
420 let v2 = ScVec::try_from((0, 1)).unwrap();
421 let expected_cmp = Ordering::Less;
422 let budget = Budget::default();
423 let actual_cmp = budget.compare(&v1, &v2).unwrap();
424 assert_eq!(expected_cmp, actual_cmp);
425 }
426 }
427
428 #[test]
429 fn test_scmap_unequal_lengths() {
430 {
431 let v1 = ScMap::sorted_from([
432 (ScVal::U32(0), ScVal::U32(0)),
433 (ScVal::U32(1), ScVal::U32(1)),
434 ])
435 .unwrap();
436 let v2 = ScMap::sorted_from([
437 (ScVal::U32(0), ScVal::U32(0)),
438 (ScVal::U32(1), ScVal::U32(1)),
439 (ScVal::U32(2), ScVal::U32(2)),
440 ])
441 .unwrap();
442 let expected_cmp = Ordering::Less;
443 let budget = Budget::default();
444 let actual_cmp = budget.compare(&v1, &v2).unwrap();
445 assert_eq!(expected_cmp, actual_cmp);
446 }
447 {
448 let v1 = ScMap::sorted_from([
449 (ScVal::U32(0), ScVal::U32(0)),
450 (ScVal::U32(1), ScVal::U32(1)),
451 (ScVal::U32(2), ScVal::U32(2)),
452 ])
453 .unwrap();
454 let v2 = ScMap::sorted_from([
455 (ScVal::U32(0), ScVal::U32(0)),
456 (ScVal::U32(1), ScVal::U32(1)),
457 ])
458 .unwrap();
459 let expected_cmp = Ordering::Greater;
460 let budget = Budget::default();
461 let actual_cmp = budget.compare(&v1, &v2).unwrap();
462 assert_eq!(expected_cmp, actual_cmp);
463 }
464 {
465 let v1 = ScMap::sorted_from([
466 (ScVal::U32(0), ScVal::U32(0)),
467 (ScVal::U32(1), ScVal::U32(1)),
468 ])
469 .unwrap();
470 let v2 = ScMap::sorted_from([
471 (ScVal::U32(0), ScVal::U32(0)),
472 (ScVal::U32(1), ScVal::U32(0)),
473 (ScVal::U32(2), ScVal::U32(2)),
474 ])
475 .unwrap();
476 let expected_cmp = Ordering::Greater;
477 let budget = Budget::default();
478 let actual_cmp = budget.compare(&v1, &v2).unwrap();
479 assert_eq!(expected_cmp, actual_cmp);
480 }
481 {
482 let v1 = ScMap::sorted_from([
483 (ScVal::U32(0), ScVal::U32(0)),
484 (ScVal::U32(1), ScVal::U32(0)),
485 (ScVal::U32(2), ScVal::U32(2)),
486 ])
487 .unwrap();
488 let v2 = ScMap::sorted_from([
489 (ScVal::U32(0), ScVal::U32(0)),
490 (ScVal::U32(1), ScVal::U32(1)),
491 ])
492 .unwrap();
493 let expected_cmp = Ordering::Less;
494 let budget = Budget::default();
495 let actual_cmp = budget.compare(&v1, &v2).unwrap();
496 assert_eq!(expected_cmp, actual_cmp);
497 }
498 }
499
500 #[test]
501 fn host_obj_discriminant_order() {
502 use crate::ScValObjRef;
513 use soroban_env_common::xdr;
514
515 let host = Host::default();
516
517 let xdr_vals = &[
518 ScVal::U64(u64::MAX),
519 ScVal::I64(i64::MAX),
520 ScVal::Timepoint(xdr::TimePoint(u64::MAX)),
521 ScVal::Duration(xdr::Duration(u64::MAX)),
522 ScVal::U128(xdr::UInt128Parts {
523 hi: u64::MAX,
524 lo: u64::MAX,
525 }),
526 ScVal::I128(xdr::Int128Parts {
527 hi: i64::MIN,
528 lo: u64::MAX,
529 }),
530 ScVal::U256(xdr::UInt256Parts {
531 hi_hi: u64::MAX,
532 hi_lo: u64::MAX,
533 lo_hi: u64::MAX,
534 lo_lo: u64::MAX,
535 }),
536 ScVal::I256(xdr::Int256Parts {
537 hi_hi: i64::MIN,
538 hi_lo: u64::MAX,
539 lo_hi: u64::MAX,
540 lo_lo: u64::MAX,
541 }),
542 ScVal::Bytes(xdr::ScBytes::try_from(vec![]).unwrap()),
543 ScVal::String(xdr::ScString::try_from(vec![]).unwrap()),
544 ScVal::Symbol(xdr::ScSymbol::try_from("very_big_symbol").unwrap()),
545 ScVal::Vec(Some(xdr::ScVec::try_from((0,)).unwrap())),
546 ScVal::Map(Some(xdr::ScMap::try_from(vec![]).unwrap())),
547 ScVal::Address(xdr::ScAddress::Contract(xdr::ContractId(xdr::Hash(
548 [0; 32],
549 )))),
550 ];
551
552 let pairs: Vec<_> = xdr_vals
553 .into_iter()
554 .map(|xdr_val| {
555 let xdr_obj = ScValObjRef::classify(&xdr_val).unwrap();
556 let host_obj = host.to_host_obj(&xdr_obj).unwrap();
557 (xdr_obj, host_obj)
558 })
559 .collect();
560
561 let mut pairs_xdr_sorted = pairs.clone();
562 let mut pairs_host_sorted = pairs_xdr_sorted.clone();
563
564 pairs_xdr_sorted.sort_by(|&(v1, _), &(v2, _)| v1.cmp(&v2));
565
566 pairs_host_sorted.sort_by(|&(_, v1), &(_, v2)| {
567 host.visit_obj_untyped(v1, |v1| {
568 host.visit_obj_untyped(v2, |v2| {
569 let v1d = host_obj_discriminant(v1);
570 let v2d = host_obj_discriminant(v2);
571 Ok(v1d.cmp(&v2d))
572 })
573 })
574 .unwrap()
575 });
576
577 let iter = pairs_xdr_sorted.into_iter().zip(pairs_host_sorted);
578
579 for ((xdr1, _), (xdr2, _)) in iter {
580 assert_eq!(xdr1, xdr2);
581 }
582 }
583
584 #[test]
596 fn compare_obj_to_small() {
597 let host = Host::default();
598 let vals: Vec<Val> = all_tags()
599 .into_iter()
600 .map(|t| example_for_tag(&host, t))
601 .collect();
602 let scvals: Vec<ScVal> = vals
603 .iter()
604 .map(|r| ScVal::try_from_val(&host, r).expect("scval"))
605 .collect();
606
607 let val_pairs = vals.iter().cartesian_product(&vals);
608 let scval_pairs = scvals.iter().cartesian_product(&scvals);
609
610 let pair_pairs = val_pairs.zip(scval_pairs);
611
612 for ((val1, val2), (scval1, scval2)) in pair_pairs {
613 let val_cmp = host.compare(val1, val2);
614 if !val_cmp.is_ok() {
615 dbg!(scval1);
616 dbg!(scval2);
617 let _ = host.compare(val1, val2);
618 panic!();
619 }
620 let scval_cmp = scval1.cmp(scval2);
621 assert_eq!(val_cmp.unwrap(), scval_cmp);
622 }
623 }
624
625 fn all_tags() -> Vec<Tag> {
626 (0_u8..=255)
627 .map(Tag::from_u8)
628 .filter(|t| {
629 !matches!(t, Tag::Bad)
631 })
632 .collect()
633 }
634
635 fn example_for_tag(host: &Host, tag: Tag) -> Val {
636 use crate::{xdr, Error};
637
638 let ex = match tag {
639 Tag::False => Val::from(false),
640 Tag::True => Val::from(true),
641 Tag::Void => Val::from(()),
642 Tag::Error => Val::from(Error::from_type_and_code(
643 ScErrorType::Context,
644 ScErrorCode::InternalError,
645 )),
646 Tag::U32Val => Val::from(u32::MAX),
647 Tag::I32Val => Val::from(i32::MAX),
648 Tag::U64Small => Val::try_from_val(host, &0_u64).unwrap(),
649 Tag::I64Small => Val::try_from_val(host, &0_i64).unwrap(),
650 Tag::TimepointSmall => {
651 Val::try_from_val(host, &ScVal::Timepoint(xdr::TimePoint(0))).unwrap()
652 }
653 Tag::DurationSmall => {
654 Val::try_from_val(host, &ScVal::Duration(xdr::Duration(0))).unwrap()
655 }
656 Tag::U128Small => Val::try_from_val(host, &0_u128).unwrap(),
657 Tag::I128Small => Val::try_from_val(host, &0_i128).unwrap(),
658 Tag::U256Small => Val::try_from_val(
659 host,
660 &ScVal::U256(xdr::UInt256Parts {
661 hi_hi: 0,
662 hi_lo: 0,
663 lo_hi: 0,
664 lo_lo: 0,
665 }),
666 )
667 .unwrap(),
668 Tag::I256Small => Val::try_from_val(
669 host,
670 &ScVal::I256(xdr::Int256Parts {
671 hi_hi: 0,
672 hi_lo: 0,
673 lo_hi: 0,
674 lo_lo: 0,
675 }),
676 )
677 .unwrap(),
678 Tag::SymbolSmall => {
679 Val::try_from_val(host, &ScVal::Symbol(xdr::ScSymbol::try_from("").unwrap()))
680 .unwrap()
681 }
682 Tag::SmallCodeUpperBound => panic!(),
683 Tag::ObjectCodeLowerBound => panic!(),
684 Tag::U64Object => Val::try_from_val(host, &u64::MAX).unwrap(),
685 Tag::I64Object => Val::try_from_val(host, &i64::MAX).unwrap(),
686 Tag::TimepointObject => {
687 Val::try_from_val(host, &ScVal::Timepoint(xdr::TimePoint(u64::MAX))).unwrap()
688 }
689 Tag::DurationObject => {
690 Val::try_from_val(host, &ScVal::Duration(xdr::Duration(u64::MAX))).unwrap()
691 }
692 Tag::U128Object => Val::try_from_val(host, &u128::MAX).unwrap(),
693 Tag::I128Object => Val::try_from_val(host, &i128::MAX).unwrap(),
694 Tag::U256Object => Val::try_from_val(
695 host,
696 &ScVal::U256(xdr::UInt256Parts {
697 hi_hi: u64::MAX,
698 hi_lo: u64::MAX,
699 lo_hi: u64::MAX,
700 lo_lo: u64::MAX,
701 }),
702 )
703 .unwrap(),
704 Tag::I256Object => Val::try_from_val(
705 host,
706 &ScVal::I256(xdr::Int256Parts {
707 hi_hi: i64::MIN,
708 hi_lo: u64::MAX,
709 lo_hi: u64::MAX,
710 lo_lo: u64::MAX,
711 }),
712 )
713 .unwrap(),
714 Tag::BytesObject => Val::try_from_val(host, &vec![1]).unwrap(),
715 Tag::StringObject => Val::try_from_val(host, &"foo").unwrap(),
716 Tag::SymbolObject => Val::try_from_val(
717 host,
718 &ScVal::Symbol(xdr::ScSymbol::try_from("a_very_big_symbol").unwrap()),
719 )
720 .unwrap(),
721 Tag::VecObject => {
722 Val::try_from_val(host, &ScVal::Vec(Some(xdr::ScVec::try_from((0,)).unwrap())))
723 .unwrap()
724 }
725 Tag::MapObject => Val::try_from_val(
726 host,
727 &ScVal::Map(Some(xdr::ScMap::try_from(vec![]).unwrap())),
728 )
729 .unwrap(),
730 Tag::AddressObject => Val::try_from_val(
731 host,
732 &ScVal::Address(xdr::ScAddress::Contract(xdr::ContractId(xdr::Hash(
733 [0; 32],
734 )))),
735 )
736 .unwrap(),
737 Tag::MuxedAddressObject => Val::try_from_val(
738 host,
739 &ScVal::Address(xdr::ScAddress::MuxedAccount(xdr::MuxedEd25519Account {
740 id: 0,
741 ed25519: xdr::Uint256([0; 32]),
742 })),
743 )
744 .unwrap(),
745 Tag::ObjectCodeUpperBound => panic!(),
746 Tag::Bad => panic!(),
747 };
751
752 assert_eq!(ex.get_tag(), tag);
753
754 ex
755 }
756}