forked from radixdlt/scrypto-challenges
-
Notifications
You must be signed in to change notification settings - Fork 0
/
requirement.rs
84 lines (76 loc) · 3.36 KB
/
requirement.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use std::cmp::Ordering;
use scrypto::prelude::*;
use sbor::*;
#[derive(Debug, Clone, TypeId, Encode, Decode, PartialEq, Eq, Describe)]
pub enum BucketContents {
Fungible(Decimal),
NonFungible(BTreeSet<NonFungibleKey>),
}
// Implement <BucketRef> == <BucketContents> comparisons
impl PartialEq<BucketContents> for BucketRef {
fn eq(&self, other: &BucketContents) -> bool {
let bucket_type = self.resource_def().resource_type();
match (bucket_type, other) {
(ResourceType::Fungible { .. }, BucketContents::Fungible(amount)) => { self.amount() == *amount },
(ResourceType::NonFungible, BucketContents::NonFungible(keys)) => {
// avoid copies by comparing sets of references. Iterates over the sets more than strictly needed to make the code simplier
let contents_keys: BTreeSet<&NonFungibleKey> = keys.iter().collect();
let self_keys = self.get_non_fungible_keys();
let self_keys: BTreeSet<&NonFungibleKey> = self_keys.iter().collect();
self_keys == contents_keys
},
(_, _) => false,
}
}
}
impl PartialOrd<BucketContents> for BucketRef {
fn partial_cmp(&self, other: &BucketContents) -> Option<Ordering> {
debug!("partial_cmd: {:?} =?= {:?}", self, other);
let bucket_type = self.resource_def().resource_type();
match (bucket_type, other) {
(ResourceType::Fungible { .. }, BucketContents::Fungible(amount)) => {
debug!("partial_cmd: Fungible {:?} =?= {:?}", self.amount(), amount);
Some(self.amount().cmp(amount))
},
(ResourceType::NonFungible, BucketContents::NonFungible(keys)) => {
// avoid copies by comparing sets of references. Iterates over the sets more than strictly needed to make the code simplier
let contents_keys: BTreeSet<&NonFungibleKey> = keys.iter().collect();
let self_keys = self.get_non_fungible_keys();
let self_keys: BTreeSet<&NonFungibleKey> = self_keys.iter().collect();
debug!("partial_cmd: NonFungible {:?} =?= {:?}", self_keys, contents_keys);
Some(self_keys.cmp(&contents_keys))
},
(_, _) => None,
}
}
}
#[derive(Debug, Clone, TypeId, Encode, Decode, PartialEq, Eq, Describe)]
pub struct BucketRequirement {
pub resource: ResourceDef,
pub contents: BucketContents,
}
impl BucketRequirement {
pub fn check_ref(&self, bucket_ref: &BucketRef) -> bool {
// same resource
if self.resource != bucket_ref.resource_def() {
return false;
}
// contents exactly match
bucket_ref == &self.contents
}
pub fn check(&self, bucket: &Bucket) -> bool {
bucket.authorize(|bucket_ref| self.check_ref(&bucket_ref))
}
pub fn check_at_least_ref(&self, bucket_ref: &BucketRef) -> bool {
debug!("check_at_least_ref: {:?} =?= {:?}", self, bucket_ref.resource_def());
// same resource
if self.resource != bucket_ref.resource_def() {
return false;
}
// bucket_ref holds at least the required contents (or more)
bucket_ref >= &self.contents
}
pub fn check_at_least(&self, bucket: &Bucket) -> bool {
bucket.authorize(|bucket_ref| self.check_at_least_ref(&bucket_ref))
}
}