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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use cosmwasm_std::{Addr, Api, CanonicalAddr, StdResult};
pub fn maybe_canonical(api: &dyn Api, human: Option<Addr>) -> StdResult<Option<CanonicalAddr>> {
human.map(|x| api.addr_canonicalize(x.as_ref())).transpose()
}
pub fn maybe_addr(api: &dyn Api, human: Option<String>) -> StdResult<Option<Addr>> {
human.map(|x| api.addr_validate(&x)).transpose()
}
pub fn calc_range_start(start_after: Option<Addr>) -> Option<Vec<u8>> {
start_after.map(|addr| {
let mut v: Vec<u8> = addr.as_bytes().into();
v.push(0);
v
})
}
pub fn calc_range_end(end_before: Option<Addr>) -> Option<Vec<u8>> {
end_before.map(|addr| addr.as_bytes().into())
}
pub fn calc_range_start_string(start_after: Option<String>) -> Option<Vec<u8>> {
start_after.map(|token_id| {
let mut v: Vec<u8> = token_id.into_bytes();
v.push(0);
v
})
}
#[cfg(test)]
mod test {
use super::*;
use cosmwasm_std::{testing::mock_dependencies, Order};
use cw_storage_plus::{Bound, Map};
pub const HOLDERS: Map<&Addr, usize> = Map::new("some_data");
const LIMIT: usize = 30;
fn addr_from_i(i: usize) -> Addr {
Addr::unchecked(format!("addr{:0>8}", i))
}
#[test]
fn calc_range_start_works_as_expected() {
let total_elements_count = 100;
let mut deps = mock_dependencies();
for i in 0..total_elements_count {
let holder = (addr_from_i(i), i);
HOLDERS
.save(&mut deps.storage, &holder.0, &holder.1)
.unwrap();
}
for j in 0..4 {
let start_after = if j == 0 {
None
} else {
Some(addr_from_i(j * LIMIT - 1))
};
let start = calc_range_start(start_after).map(Bound::ExclusiveRaw);
let holders = HOLDERS
.keys(&deps.storage, start, None, Order::Ascending)
.take(LIMIT)
.collect::<StdResult<Vec<_>>>()
.unwrap();
for (i, holder) in holders.into_iter().enumerate() {
let global_index = j * LIMIT + i;
assert_eq!(holder, addr_from_i(global_index));
}
}
}
#[test]
fn calc_range_end_works_as_expected() {
let total_elements_count = 100;
let mut deps = mock_dependencies();
for i in 0..total_elements_count {
let holder = (addr_from_i(i), i);
HOLDERS
.save(&mut deps.storage, &holder.0, &holder.1)
.unwrap();
}
for j in 0..4 {
let end_before = Some(addr_from_i(total_elements_count - j * LIMIT));
let end = calc_range_end(end_before).map(Bound::ExclusiveRaw);
let holders = HOLDERS
.keys(&deps.storage, None, end, Order::Descending)
.take(LIMIT)
.collect::<StdResult<Vec<_>>>()
.unwrap();
for (i, holder) in holders.into_iter().enumerate() {
let global_index = total_elements_count - i - j * LIMIT - 1;
assert_eq!(holder, addr_from_i(global_index));
}
}
}
#[ignore]
#[test]
fn add_more_tests() {}
}