generic_query/
value_ordering.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4use cosmwasm_std::{StdError, StdResult, Uint512};
5use serde_cw_value::Value;
6
7#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
8#[serde(rename_all = "snake_case")]
9pub enum ValueOrdering {
10    UnitAbove,
11    UnitAboveEqual,
12    UnitBelow,
13    UnitBelowEqual,
14    Equal,
15    NotEqual,
16}
17
18impl ValueOrdering {
19    pub fn val_cmp(&self, lhs: &Value, rhs: &Value) -> StdResult<bool> {
20        let res = match self {
21            ValueOrdering::UnitAbove => lhs.bt_g(rhs)?,
22            ValueOrdering::UnitAboveEqual => lhs.be_g(rhs)?,
23            ValueOrdering::UnitBelow => lhs.lt_g(rhs)?,
24            ValueOrdering::UnitBelowEqual => lhs.le_g(rhs)?,
25            ValueOrdering::Equal => lhs.eq(rhs),
26            ValueOrdering::NotEqual => lhs.ne(rhs),
27        };
28        Ok(res)
29    }
30}
31
32pub trait ValueOrd {
33    fn lt_g(&self, other: &Self) -> StdResult<bool>;
34    fn le_g(&self, other: &Self) -> StdResult<bool>;
35    fn bt_g(&self, other: &Self) -> StdResult<bool>;
36    fn be_g(&self, other: &Self) -> StdResult<bool>;
37    fn equal(&self, other: &Self) -> bool;
38}
39
40/// Only supporting numbers and big numbers for now
41impl ValueOrd for Value {
42    fn lt_g(&self, other: &Self) -> StdResult<bool> {
43        match (self, other) {
44            (Value::String(str_num), Value::String(oth)) => {
45                let big_num: Uint512 = str_num.parse()?;
46                let big_oth: Uint512 = oth.parse()?;
47                Ok(big_num < big_oth)
48            }
49            (Value::U64(n), Value::U64(o)) => Ok(n < o),
50            (Value::U32(n), Value::U32(o)) => Ok(n < o),
51            (Value::U16(n), Value::U16(o)) => Ok(n < o),
52            (Value::U8(n), Value::U8(o)) => Ok(n < o),
53            _ => Err(StdError::parse_err(
54                "number",
55                "Failed to parse to Uint512 and to u64",
56            )),
57        }
58    }
59
60    fn le_g(&self, other: &Self) -> StdResult<bool> {
61        match (self, other) {
62            (Value::String(str_num), Value::String(oth)) => {
63                let big_num: Uint512 = str_num.parse()?;
64                let big_oth: Uint512 = oth.parse()?;
65                Ok(big_num <= big_oth)
66            }
67            (Value::U64(n), Value::U64(o)) => Ok(n <= o),
68            (Value::U32(n), Value::U32(o)) => Ok(n <= o),
69            (Value::U16(n), Value::U16(o)) => Ok(n <= o),
70            (Value::U8(n), Value::U8(o)) => Ok(n <= o),
71            _ => Err(StdError::parse_err(
72                "number",
73                "Failed to parse to Uint512 and to u64",
74            )),
75        }
76    }
77
78    fn bt_g(&self, other: &Self) -> StdResult<bool> {
79        match (self, other) {
80            (Value::String(str_num), Value::String(oth)) => {
81                let big_num: Uint512 = str_num.parse()?;
82                let big_oth: Uint512 = oth.parse()?;
83                Ok(big_num > big_oth)
84            }
85            (Value::U64(n), Value::U64(o)) => Ok(n > o),
86            (Value::U32(n), Value::U32(o)) => Ok(n > o),
87            (Value::U16(n), Value::U16(o)) => Ok(n > o),
88            (Value::U8(n), Value::U8(o)) => Ok(n > o),
89            _ => Err(StdError::parse_err(
90                "number",
91                "Failed to parse to Uint512 and to u64",
92            )),
93        }
94    }
95
96    fn be_g(&self, other: &Self) -> StdResult<bool> {
97        match (self, other) {
98            (Value::String(str_num), Value::String(oth)) => {
99                let big_num: Uint512 = str_num.parse()?;
100                let big_oth: Uint512 = oth.parse()?;
101                Ok(big_num >= big_oth)
102            }
103            (Value::U64(n), Value::U64(o)) => Ok(n >= o),
104            (Value::U32(n), Value::U32(o)) => Ok(n >= o),
105            (Value::U16(n), Value::U16(o)) => Ok(n >= o),
106            (Value::U8(n), Value::U8(o)) => Ok(n >= o),
107            _ => Err(StdError::parse_err(
108                "number",
109                "Failed to parse to Uint512 and to u64",
110            )),
111        }
112    }
113
114    fn equal(&self, other: &Self) -> bool {
115        self.eq(other)
116    }
117}
118
119#[cfg(test)]
120mod test {
121    use cosmwasm_std::StdError;
122
123    use super::ValueOrd;
124
125    #[test]
126    fn test_lt_g() {
127        // less
128        assert!(serde_cw_value::to_value(5_u64)
129            .unwrap()
130            .lt_g(&serde_cw_value::to_value(6_u64).unwrap())
131            .unwrap());
132        assert!(serde_cw_value::to_value("5")
133            .unwrap()
134            .lt_g(&serde_cw_value::to_value("6").unwrap())
135            .unwrap());
136        // equal
137        assert!(!serde_cw_value::to_value(5_u64)
138            .unwrap()
139            .lt_g(&serde_cw_value::to_value(5_u64).unwrap())
140            .unwrap());
141        assert!(!serde_cw_value::to_value("5")
142            .unwrap()
143            .lt_g(&serde_cw_value::to_value("5").unwrap())
144            .unwrap());
145        // bigger than
146        assert!(!serde_cw_value::to_value(42_u64)
147            .unwrap()
148            .lt_g(&serde_cw_value::to_value(8_u64).unwrap())
149            .unwrap());
150        assert!(!serde_cw_value::to_value("42")
151            .unwrap()
152            .lt_g(&serde_cw_value::to_value("8").unwrap())
153            .unwrap());
154    }
155
156    #[test]
157    fn test_lt_negative() {
158        let different_types = serde_cw_value::to_value(5_u64)
159            .unwrap()
160            .lt_g(&serde_cw_value::to_value("6").unwrap())
161            .unwrap_err();
162        assert!(matches!(different_types, StdError::ParseErr { .. }));
163
164        let different_types = serde_cw_value::to_value("5")
165            .unwrap()
166            .lt_g(&serde_cw_value::to_value(6_u64).unwrap())
167            .unwrap_err();
168        assert!(matches!(different_types, StdError::ParseErr { .. }));
169
170        let invalid_value = serde_cw_value::to_value("foo")
171            .unwrap()
172            .lt_g(&serde_cw_value::to_value(6_u64).unwrap())
173            .unwrap_err();
174        assert!(matches!(invalid_value, StdError::ParseErr { .. }));
175
176        let invalid_value = serde_cw_value::to_value("5")
177            .unwrap()
178            .lt_g(&serde_cw_value::to_value("bar").unwrap())
179            .unwrap_err();
180        assert!(matches!(invalid_value, StdError::GenericErr { .. }));
181    }
182
183    #[test]
184    fn test_le_g() {
185        // less
186        assert!(serde_cw_value::to_value(5_u64)
187            .unwrap()
188            .le_g(&serde_cw_value::to_value(6_u64).unwrap())
189            .unwrap());
190        assert!(serde_cw_value::to_value("5")
191            .unwrap()
192            .le_g(&serde_cw_value::to_value("6").unwrap())
193            .unwrap());
194        // equal
195        assert!(serde_cw_value::to_value(5_u64)
196            .unwrap()
197            .le_g(&serde_cw_value::to_value(5_u64).unwrap())
198            .unwrap());
199        assert!(serde_cw_value::to_value("5")
200            .unwrap()
201            .le_g(&serde_cw_value::to_value("5").unwrap())
202            .unwrap());
203        // bigger than
204        assert!(!serde_cw_value::to_value(42_u64)
205            .unwrap()
206            .le_g(&serde_cw_value::to_value(8_u64).unwrap())
207            .unwrap());
208        assert!(!serde_cw_value::to_value("42")
209            .unwrap()
210            .le_g(&serde_cw_value::to_value("8").unwrap())
211            .unwrap());
212    }
213
214    #[test]
215    fn test_le_negative() {
216        let different_types = serde_cw_value::to_value(5_u64)
217            .unwrap()
218            .le_g(&serde_cw_value::to_value("6").unwrap())
219            .unwrap_err();
220        assert!(matches!(different_types, StdError::ParseErr { .. }));
221
222        let different_types = serde_cw_value::to_value("5")
223            .unwrap()
224            .le_g(&serde_cw_value::to_value(6_u64).unwrap())
225            .unwrap_err();
226        assert!(matches!(different_types, StdError::ParseErr { .. }));
227
228        let invalid_value = serde_cw_value::to_value("foo")
229            .unwrap()
230            .le_g(&serde_cw_value::to_value(6_u64).unwrap())
231            .unwrap_err();
232        assert!(matches!(invalid_value, StdError::ParseErr { .. }));
233
234        let invalid_value = serde_cw_value::to_value("5")
235            .unwrap()
236            .le_g(&serde_cw_value::to_value("bar").unwrap())
237            .unwrap_err();
238        assert!(matches!(invalid_value, StdError::GenericErr { .. }));
239    }
240
241    #[test]
242    fn test_bt_g() {
243        // less
244        assert!(!serde_cw_value::to_value(5_u64)
245            .unwrap()
246            .bt_g(&serde_cw_value::to_value(6_u64).unwrap())
247            .unwrap());
248        assert!(!serde_cw_value::to_value("5")
249            .unwrap()
250            .bt_g(&serde_cw_value::to_value("6").unwrap())
251            .unwrap());
252        // equal
253        assert!(!serde_cw_value::to_value(5_u64)
254            .unwrap()
255            .bt_g(&serde_cw_value::to_value(5_u64).unwrap())
256            .unwrap());
257        assert!(!serde_cw_value::to_value("5")
258            .unwrap()
259            .bt_g(&serde_cw_value::to_value("5").unwrap())
260            .unwrap());
261        // bigger than
262        assert!(serde_cw_value::to_value(42_u64)
263            .unwrap()
264            .bt_g(&serde_cw_value::to_value(8_u64).unwrap())
265            .unwrap());
266        assert!(serde_cw_value::to_value("42")
267            .unwrap()
268            .bt_g(&serde_cw_value::to_value("8").unwrap())
269            .unwrap());
270    }
271
272    #[test]
273    fn test_bt_negative() {
274        let different_types = serde_cw_value::to_value(5_u64)
275            .unwrap()
276            .bt_g(&serde_cw_value::to_value("6").unwrap())
277            .unwrap_err();
278        assert!(matches!(different_types, StdError::ParseErr { .. }));
279
280        let different_types = serde_cw_value::to_value("5")
281            .unwrap()
282            .bt_g(&serde_cw_value::to_value(6_u64).unwrap())
283            .unwrap_err();
284        assert!(matches!(different_types, StdError::ParseErr { .. }));
285
286        let invalid_value = serde_cw_value::to_value("foo")
287            .unwrap()
288            .bt_g(&serde_cw_value::to_value(6_u64).unwrap())
289            .unwrap_err();
290        assert!(matches!(invalid_value, StdError::ParseErr { .. }));
291
292        let invalid_value = serde_cw_value::to_value("5")
293            .unwrap()
294            .bt_g(&serde_cw_value::to_value("bar").unwrap())
295            .unwrap_err();
296        assert!(matches!(invalid_value, StdError::GenericErr { .. }));
297    }
298
299    #[test]
300    fn test_be_g() {
301        // less
302        assert!(!serde_cw_value::to_value(5_u64)
303            .unwrap()
304            .be_g(&serde_cw_value::to_value(6_u64).unwrap())
305            .unwrap());
306        assert!(!serde_cw_value::to_value("5")
307            .unwrap()
308            .be_g(&serde_cw_value::to_value("6").unwrap())
309            .unwrap());
310        // equal
311        assert!(serde_cw_value::to_value(5_u64)
312            .unwrap()
313            .be_g(&serde_cw_value::to_value(5_u64).unwrap())
314            .unwrap());
315        assert!(serde_cw_value::to_value("5")
316            .unwrap()
317            .be_g(&serde_cw_value::to_value("5").unwrap())
318            .unwrap());
319        // bigger than
320        assert!(serde_cw_value::to_value(42_u64)
321            .unwrap()
322            .be_g(&serde_cw_value::to_value(8_u64).unwrap())
323            .unwrap());
324        assert!(serde_cw_value::to_value("42")
325            .unwrap()
326            .be_g(&serde_cw_value::to_value("8").unwrap())
327            .unwrap());
328    }
329
330    #[test]
331    fn test_be_negative() {
332        let different_types = serde_cw_value::to_value(5_u64)
333            .unwrap()
334            .be_g(&serde_cw_value::to_value("6").unwrap())
335            .unwrap_err();
336        assert!(matches!(different_types, StdError::ParseErr { .. }));
337
338        let different_types = serde_cw_value::to_value("5")
339            .unwrap()
340            .be_g(&serde_cw_value::to_value(6_u64).unwrap())
341            .unwrap_err();
342        assert!(matches!(different_types, StdError::ParseErr { .. }));
343
344        let invalid_value = serde_cw_value::to_value("foo")
345            .unwrap()
346            .be_g(&serde_cw_value::to_value(6_u64).unwrap())
347            .unwrap_err();
348        assert!(matches!(invalid_value, StdError::ParseErr { .. }));
349
350        let invalid_value = serde_cw_value::to_value("5")
351            .unwrap()
352            .be_g(&serde_cw_value::to_value("bar").unwrap())
353            .unwrap_err();
354        assert!(matches!(invalid_value, StdError::GenericErr { .. }));
355    }
356
357    #[test]
358    fn test_equal() {
359        // less
360        assert!(!serde_cw_value::to_value(5_u64)
361            .unwrap()
362            .equal(&serde_cw_value::to_value(6_u64).unwrap()));
363        assert!(!serde_cw_value::to_value("5")
364            .unwrap()
365            .equal(&serde_cw_value::to_value("6").unwrap()));
366        // equal
367        assert!(serde_cw_value::to_value(5_u64)
368            .unwrap()
369            .equal(&serde_cw_value::to_value(5_u64).unwrap()));
370        assert!(serde_cw_value::to_value("5")
371            .unwrap()
372            .equal(&serde_cw_value::to_value("5").unwrap()));
373        // bigger than
374        assert!(!serde_cw_value::to_value(42_u64)
375            .unwrap()
376            .equal(&serde_cw_value::to_value(8_u64).unwrap()));
377        assert!(!serde_cw_value::to_value("42")
378            .unwrap()
379            .equal(&serde_cw_value::to_value("8").unwrap()));
380
381        // Equal can match not only numbers
382        assert!(serde_cw_value::to_value(r#"{"foo": "bar"}"#)
383            .unwrap()
384            .equal(&serde_cw_value::to_value(r#"{"foo": "bar"}"#).unwrap()));
385        assert!(!serde_cw_value::to_value(r#"{"foo": "bar"}"#)
386            .unwrap()
387            .equal(&serde_cw_value::to_value(r#"{"bar": "foo"}"#).unwrap()));
388    }
389}