1use cosmwasm_std::{Addr, Api, CanonicalAddr, StdResult};
2
3pub fn maybe_canonical(api: &dyn Api, human: Option<Addr>) -> StdResult<Option<CanonicalAddr>> {
5 human.map(|x| api.addr_canonicalize(x.as_ref())).transpose()
6}
7
8pub fn maybe_addr(api: &dyn Api, human: Option<String>) -> StdResult<Option<Addr>> {
10 human.map(|x| api.addr_validate(&x)).transpose()
11}
12
13pub fn calc_range_start(start_after: Option<Addr>) -> Option<Vec<u8>> {
15 start_after.map(|addr| {
16 let mut v: Vec<u8> = addr.as_bytes().into();
17 v.push(0);
18 v
19 })
20}
21
22pub fn calc_range_end(end_before: Option<Addr>) -> Option<Vec<u8>> {
24 end_before.map(|addr| addr.as_bytes().into())
25}
26
27pub fn calc_range_start_string(start_after: Option<String>) -> Option<Vec<u8>> {
29 start_after.map(|token_id| {
30 let mut v: Vec<u8> = token_id.into_bytes();
31 v.push(0);
32 v
33 })
34}
35
36#[cfg(test)]
37mod test {
38 use super::*;
39 use cosmwasm_std::{testing::mock_dependencies, Order};
40 use cw_storage_plus::{Bound, Map};
41
42 pub const HOLDERS: Map<&Addr, usize> = Map::new("some_data");
43 const LIMIT: usize = 30;
44
45 fn addr_from_i(i: usize) -> Addr {
46 Addr::unchecked(format!("addr{:0>8}", i))
47 }
48
49 #[test]
50 fn calc_range_start_works_as_expected() {
51 let total_elements_count = 100;
52 let mut deps = mock_dependencies();
53 for i in 0..total_elements_count {
54 let holder = (addr_from_i(i), i);
55 HOLDERS
56 .save(&mut deps.storage, &holder.0, &holder.1)
57 .unwrap();
58 }
59
60 for j in 0..4 {
61 let start_after = if j == 0 {
62 None
63 } else {
64 Some(addr_from_i(j * LIMIT - 1))
65 };
66
67 let start = calc_range_start(start_after).map(Bound::ExclusiveRaw);
68
69 let holders = HOLDERS
70 .keys(&deps.storage, start, None, Order::Ascending)
71 .take(LIMIT)
72 .collect::<StdResult<Vec<_>>>()
73 .unwrap();
74
75 for (i, holder) in holders.into_iter().enumerate() {
76 let global_index = j * LIMIT + i;
77 assert_eq!(holder, addr_from_i(global_index));
78 }
79 }
80 }
81
82 #[test]
83 fn calc_range_end_works_as_expected() {
84 let total_elements_count = 100;
85 let mut deps = mock_dependencies();
86 for i in 0..total_elements_count {
87 let holder = (addr_from_i(i), i);
88 HOLDERS
89 .save(&mut deps.storage, &holder.0, &holder.1)
90 .unwrap();
91 }
92
93 for j in 0..4 {
94 let end_before = Some(addr_from_i(total_elements_count - j * LIMIT));
95
96 let end = calc_range_end(end_before).map(Bound::ExclusiveRaw);
97
98 let holders = HOLDERS
99 .keys(&deps.storage, None, end, Order::Descending)
100 .take(LIMIT)
101 .collect::<StdResult<Vec<_>>>()
102 .unwrap();
103
104 for (i, holder) in holders.into_iter().enumerate() {
105 let global_index = total_elements_count - i - j * LIMIT - 1;
106 assert_eq!(holder, addr_from_i(global_index));
107 }
108 }
109 }
110
111 #[ignore]
113 #[test]
114 fn add_more_tests() {}
115}