cw_storage_plus/
bound.rs

1#![cfg(feature = "iterator")]
2
3use cosmwasm_std::Addr;
4use std::marker::PhantomData;
5
6use crate::de::KeyDeserialize;
7use crate::{Prefixer, PrimaryKey};
8
9/// `RawBound` is used to define the two ends of a range, more explicit than `Option<u8>`.
10/// `None` means that we don't limit that side of the range at all.
11/// `Inclusive` means we use the given bytes as a limit and *include* anything at that exact key.
12/// `Exclusive` means we use the given bytes as a limit and *exclude* anything at that exact key.
13/// See `Bound` for a type safe way to build these bounds.
14#[derive(Clone, Debug)]
15pub enum RawBound {
16    Inclusive(Vec<u8>),
17    Exclusive(Vec<u8>),
18}
19
20/// `Bound` is used to define the two ends of a range.
21/// `None` means that we don't limit that side of the range at all.
22/// `Inclusive` means we use the given value as a limit and *include* anything at that exact key.
23/// `Exclusive` means we use the given value as a limit and *exclude* anything at that exact key.
24#[derive(Clone, Debug)]
25pub enum Bound<'a, K: PrimaryKey<'a>> {
26    Inclusive((K, PhantomData<&'a bool>)),
27    Exclusive((K, PhantomData<&'a bool>)),
28    InclusiveRaw(Vec<u8>),
29    ExclusiveRaw(Vec<u8>),
30}
31
32impl<'a, K: PrimaryKey<'a>> Bound<'a, K> {
33    pub fn inclusive<T: Into<K>>(k: T) -> Self {
34        Self::Inclusive((k.into(), PhantomData))
35    }
36
37    pub fn exclusive<T: Into<K>>(k: T) -> Self {
38        Self::Exclusive((k.into(), PhantomData))
39    }
40
41    pub fn to_raw_bound(&self) -> RawBound {
42        match self {
43            Bound::Inclusive((k, _)) => RawBound::Inclusive(k.joined_key()),
44            Bound::Exclusive((k, _)) => RawBound::Exclusive(k.joined_key()),
45            Bound::ExclusiveRaw(raw_k) => RawBound::Exclusive(raw_k.clone()),
46            Bound::InclusiveRaw(raw_k) => RawBound::Inclusive(raw_k.clone()),
47        }
48    }
49}
50
51#[derive(Clone, Debug)]
52pub enum PrefixBound<'a, K: Prefixer<'a>> {
53    Inclusive((K, PhantomData<&'a bool>)),
54    Exclusive((K, PhantomData<&'a bool>)),
55}
56
57impl<'a, K: Prefixer<'a>> PrefixBound<'a, K> {
58    pub fn inclusive<T: Into<K>>(k: T) -> Self {
59        Self::Inclusive((k.into(), PhantomData))
60    }
61
62    pub fn exclusive<T: Into<K>>(k: T) -> Self {
63        Self::Exclusive((k.into(), PhantomData))
64    }
65
66    pub fn to_raw_bound(&self) -> RawBound {
67        match self {
68            PrefixBound::Exclusive((k, _)) => RawBound::Exclusive(k.joined_prefix()),
69            PrefixBound::Inclusive((k, _)) => RawBound::Inclusive(k.joined_prefix()),
70        }
71    }
72}
73
74pub trait Bounder<'a>: PrimaryKey<'a> + Sized {
75    fn inclusive_bound(self) -> Option<Bound<'a, Self>>;
76    fn exclusive_bound(self) -> Option<Bound<'a, Self>>;
77}
78
79impl<'a> Bounder<'a> for () {
80    fn inclusive_bound(self) -> Option<Bound<'a, Self>> {
81        None
82    }
83    fn exclusive_bound(self) -> Option<Bound<'a, Self>> {
84        None
85    }
86}
87
88impl<'a> Bounder<'a> for &'a [u8] {
89    fn inclusive_bound(self) -> Option<Bound<'a, Self>> {
90        Some(Bound::inclusive(self))
91    }
92    fn exclusive_bound(self) -> Option<Bound<'a, Self>> {
93        Some(Bound::exclusive(self))
94    }
95}
96
97impl<
98        'a,
99        T: PrimaryKey<'a> + KeyDeserialize + Prefixer<'a> + Clone,
100        U: PrimaryKey<'a> + KeyDeserialize + Clone,
101    > Bounder<'a> for (T, U)
102{
103    fn inclusive_bound(self) -> Option<Bound<'a, Self>> {
104        Some(Bound::inclusive(self))
105    }
106    fn exclusive_bound(self) -> Option<Bound<'a, Self>> {
107        Some(Bound::exclusive(self))
108    }
109}
110
111impl<
112        'a,
113        T: PrimaryKey<'a> + Prefixer<'a> + Clone,
114        U: PrimaryKey<'a> + Prefixer<'a> + KeyDeserialize + Clone,
115        V: PrimaryKey<'a> + KeyDeserialize + Clone,
116    > Bounder<'a> for (T, U, V)
117{
118    fn inclusive_bound(self) -> Option<Bound<'a, Self>> {
119        Some(Bound::inclusive(self))
120    }
121    fn exclusive_bound(self) -> Option<Bound<'a, Self>> {
122        Some(Bound::exclusive(self))
123    }
124}
125
126impl<'a> Bounder<'a> for &'a str {
127    fn inclusive_bound(self) -> Option<Bound<'a, Self>> {
128        Some(Bound::inclusive(self))
129    }
130    fn exclusive_bound(self) -> Option<Bound<'a, Self>> {
131        Some(Bound::exclusive(self))
132    }
133}
134
135impl<'a> Bounder<'a> for String {
136    fn inclusive_bound(self) -> Option<Bound<'a, Self>> {
137        Some(Bound::inclusive(self))
138    }
139    fn exclusive_bound(self) -> Option<Bound<'a, Self>> {
140        Some(Bound::exclusive(self))
141    }
142}
143
144impl<'a> Bounder<'a> for Vec<u8> {
145    fn inclusive_bound(self) -> Option<Bound<'a, Self>> {
146        Some(Bound::inclusive(self))
147    }
148    fn exclusive_bound(self) -> Option<Bound<'a, Self>> {
149        Some(Bound::exclusive(self))
150    }
151}
152
153impl<'a> Bounder<'a> for &'a Addr {
154    fn inclusive_bound(self) -> Option<Bound<'a, Self>> {
155        Some(Bound::inclusive(self))
156    }
157    fn exclusive_bound(self) -> Option<Bound<'a, Self>> {
158        Some(Bound::exclusive(self))
159    }
160}
161
162impl<'a> Bounder<'a> for Addr {
163    fn inclusive_bound(self) -> Option<Bound<'a, Self>> {
164        Some(Bound::inclusive(self))
165    }
166    fn exclusive_bound(self) -> Option<Bound<'a, Self>> {
167        Some(Bound::exclusive(self))
168    }
169}
170
171macro_rules! integer_bound {
172    (for $($t:ty),+) => {
173        $(impl<'a> Bounder<'a> for $t {
174            fn inclusive_bound(self) -> Option<Bound<'a, Self>> {
175                Some(Bound::inclusive(self))
176            }
177            fn exclusive_bound(self) -> Option<Bound<'a, Self>> {
178                Some(Bound::exclusive(self))
179            }
180        })*
181    }
182}
183
184integer_bound!(for i8, u8, i16, u16, i32, u32, i64, u64);