1use crate::{Access, Op, StateRead};
2use bitflags::bitflags;
3
4#[derive(Debug, Copy, Clone, PartialEq, Eq)]
6pub struct Effects(u8);
7
8bitflags! {
9 impl Effects: u8 {
10 const KeyRange = 1 << 0;
12 const KeyRangeExtern = 1 << 1;
14 const ThisAddress = 1 << 2;
16 const ThisContractAddress = 1 << 3;
18 }
19}
20
21pub fn analyze(ops: &[Op]) -> Effects {
23 let mut effects = Effects::empty();
24
25 for op in ops {
26 match op {
27 Op::StateRead(StateRead::KeyRangeExtern) => effects |= Effects::KeyRangeExtern,
28 Op::StateRead(StateRead::KeyRange) => effects |= Effects::KeyRange,
29 Op::Access(Access::ThisAddress) => effects |= Effects::ThisAddress,
30 Op::Access(Access::ThisContractAddress) => effects |= Effects::ThisContractAddress,
31 _ => {}
32 }
33
34 if effects == Effects::all() {
36 break;
37 }
38 }
39 effects
40}
41
42#[cfg(test)]
43mod test {
44 use super::{analyze, Access, Effects, Op, StateRead};
45
46 #[test]
47 fn none() {
48 let ops = &[];
49 assert_eq!(analyze(ops), Effects::empty());
50 }
51
52 #[test]
53 fn key_range() {
54 let ops = &[Op::StateRead(StateRead::KeyRange)];
55 let effects = analyze(ops);
56 assert!(effects.contains(Effects::KeyRange));
57 }
58
59 #[test]
60 fn key_range_extern() {
61 let ops = &[Op::StateRead(StateRead::KeyRangeExtern)];
62 let effects = analyze(ops);
63 assert!(effects.contains(Effects::KeyRangeExtern));
64 }
65
66 #[test]
67 fn this_address() {
68 let ops = &[Op::Access(Access::ThisAddress)];
69 let effects = analyze(ops);
70 assert!(effects.contains(Effects::ThisAddress));
71 }
72
73 #[test]
74 fn this_contract_address() {
75 let ops = &[Op::Access(Access::ThisContractAddress)];
76 let effects = analyze(ops);
77 assert!(effects.contains(Effects::ThisContractAddress));
78 }
79
80 #[test]
81 fn all_effects() {
82 let ops = &[
83 Op::StateRead(StateRead::KeyRange),
84 Op::StateRead(StateRead::KeyRangeExtern),
85 Op::Access(Access::ThisAddress),
86 Op::Access(Access::ThisContractAddress),
87 ];
88 let effects = analyze(ops);
89 assert!(effects.contains(Effects::KeyRange));
90 assert!(effects.contains(Effects::KeyRangeExtern));
91 assert!(effects.contains(Effects::ThisAddress));
92 assert!(effects.contains(Effects::ThisContractAddress));
93 }
94}