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