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_schema::cw_serde;

use cosmwasm_std::{StdError, StdResult, Uint512};
use serde_cw_value::Value;

#[cw_serde]
pub enum ValueOrdering {
    UnitAbove,
    UnitAboveEqual,
    UnitBelow,
    UnitBelowEqual,
    Equal,
    NotEqual,
}

impl ValueOrdering {
    pub fn val_cmp(&self, lhs: &Value, rhs: &Value) -> StdResult<bool> {
        let res = match self {
            ValueOrdering::UnitAbove => lhs.bt_g(rhs)?,
            ValueOrdering::UnitAboveEqual => lhs.be_g(rhs)?,
            ValueOrdering::UnitBelow => lhs.lt_g(rhs)?,
            ValueOrdering::UnitBelowEqual => lhs.le_g(rhs)?,
            ValueOrdering::Equal => lhs.eq(rhs),
            ValueOrdering::NotEqual => lhs.ne(rhs),
        };
        Ok(res)
    }
}

pub trait ValueOrd {
    fn lt_g(&self, other: &Self) -> StdResult<bool>;
    fn le_g(&self, other: &Self) -> StdResult<bool>;
    fn bt_g(&self, other: &Self) -> StdResult<bool>;
    fn be_g(&self, other: &Self) -> StdResult<bool>;
    fn equal(&self, other: &Self) -> bool;
}

/// Only supporting numbers and big numbers for now
impl ValueOrd for Value {
    fn lt_g(&self, other: &Self) -> StdResult<bool> {
        match (self, other) {
            (Value::String(str_num), Value::String(oth)) => {
                let big_num: Uint512 = str_num.parse()?;
                let big_oth: Uint512 = oth.parse()?;
                Ok(big_num < big_oth)
            }
            (Value::U64(n), Value::U64(o)) => Ok(n < o),
            (Value::U32(n), Value::U32(o)) => Ok(n < o),
            (Value::U16(n), Value::U16(o)) => Ok(n < o),
            (Value::U8(n), Value::U8(o)) => Ok(n < o),
            _ => Err(StdError::parse_err(
                "number",
                "Failed to parse to Uint512 and to u64",
            )),
        }
    }

    fn le_g(&self, other: &Self) -> StdResult<bool> {
        match (self, other) {
            (Value::String(str_num), Value::String(oth)) => {
                let big_num: Uint512 = str_num.parse()?;
                let big_oth: Uint512 = oth.parse()?;
                Ok(big_num <= big_oth)
            }
            (Value::U64(n), Value::U64(o)) => Ok(n <= o),
            (Value::U32(n), Value::U32(o)) => Ok(n <= o),
            (Value::U16(n), Value::U16(o)) => Ok(n <= o),
            (Value::U8(n), Value::U8(o)) => Ok(n <= o),
            _ => Err(StdError::parse_err(
                "number",
                "Failed to parse to Uint512 and to u64",
            )),
        }
    }

    fn bt_g(&self, other: &Self) -> StdResult<bool> {
        match (self, other) {
            (Value::String(str_num), Value::String(oth)) => {
                let big_num: Uint512 = str_num.parse()?;
                let big_oth: Uint512 = oth.parse()?;
                Ok(big_num > big_oth)
            }
            (Value::U64(n), Value::U64(o)) => Ok(n > o),
            (Value::U32(n), Value::U32(o)) => Ok(n > o),
            (Value::U16(n), Value::U16(o)) => Ok(n > o),
            (Value::U8(n), Value::U8(o)) => Ok(n > o),
            _ => Err(StdError::parse_err(
                "number",
                "Failed to parse to Uint512 and to u64",
            )),
        }
    }

    fn be_g(&self, other: &Self) -> StdResult<bool> {
        match (self, other) {
            (Value::String(str_num), Value::String(oth)) => {
                let big_num: Uint512 = str_num.parse()?;
                let big_oth: Uint512 = oth.parse()?;
                Ok(big_num >= big_oth)
            }
            (Value::U64(n), Value::U64(o)) => Ok(n >= o),
            (Value::U32(n), Value::U32(o)) => Ok(n >= o),
            (Value::U16(n), Value::U16(o)) => Ok(n >= o),
            (Value::U8(n), Value::U8(o)) => Ok(n >= o),
            _ => Err(StdError::parse_err(
                "number",
                "Failed to parse to Uint512 and to u64",
            )),
        }
    }

    fn equal(&self, other: &Self) -> bool {
        self.eq(other)
    }
}