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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use std::fmt::{self, Debug, Display};

use derive_more::{Deref, DerefMut};

mod constants;

/// The error code.
#[derive(Clone, Copy, Eq, PartialEq, Hash, Default, Deref, DerefMut)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct Code(i32);

impl Display for Code {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!("{:#06X}", *self))
    }
}

impl Debug for Code {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!("[{:#06X}] {}", self.0, self.as_err_str()))
    }
}

impl Code {
    /// Error code == 0. It should not raised in any real errors.
    pub fn success(&self) -> bool {
        self.0 == 0
    }

    const fn as_err_str(&self) -> &'static str {
        if self.0 == 0 {
            return "Success";
        }
        match constants::error_str_of(self.0 as _) {
            Some(s) => s,
            None => "Incomplete",
        }
    }
    pub(crate) const fn _priv_err_str(&self) -> Option<&'static str> {
        constants::error_str_of(self.0 as _)
    }
}

/// Constants
impl Code {
    #[allow(non_upper_case_globals)]
    #[deprecated(since = "0.9.0", note = "Use Code::FAILED instead")]
    pub const Failed: Code = Code(0xFFFF);
    #[allow(non_upper_case_globals)]
    #[deprecated(since = "0.9.0", note = "Use Code::SUCCESS instead")]
    pub const Success: Code = Code(0);

    pub const FAILED: Code = Code(0xFFFF);
    pub const SUCCESS: Code = Code(0);

    pub const COLUMN_EXISTS: Code = Code(0x036B);
    pub const COLUMN_NOT_EXIST: Code = Code(0x036C);
    pub const TAG_ALREADY_EXIST: Code = Code(0x0369);
    pub const TAG_NOT_EXIST: Code = Code(0x036A);
    pub const MODIFIED_ALREADY: Code = Code(0x264B);
    pub const INVALID_COLUMN_NAME: Code = Code(0x2602);
    pub const TABLE_NOT_EXIST: Code = Code(0x2603);
    pub const STABLE_NOT_EXIST: Code = Code(0x0362);
    pub const INVALID_ROW_BYTES: Code = Code(0x036F);
    pub const DUPLICATED_COLUMN_NAMES: Code = Code(0x263C);
    pub const NO_COLUMN_CAN_BE_DROPPED: Code = Code(0x2651);
}

macro_rules! _impl_fmt {
    ($fmt:ident) => {
        impl fmt::$fmt for Code {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                fmt::$fmt::fmt(&self.0, f)
            }
        }
    };
}

_impl_fmt!(LowerHex);
_impl_fmt!(UpperHex);

macro_rules! _impl_from {
    ($($from:ty) *) => {
        $(
            impl From<$from> for Code {
                #[inline]
                fn from(c: $from) -> Self {
                    Self(c as i32 & 0xFFFF)
                }
            }
            impl From<Code> for $from {
                #[inline]
                fn from(c: Code) -> Self {
                    c.0 as _
                }
            }
        )*
    };
}

_impl_from!(i8 u8 i16 i32 u16 u32 i64 u64);

impl Code {
    /// Code from raw primitive type.
    pub const fn new(code: i32) -> Self {
        Code(code)
    }
}

impl PartialEq<usize> for Code {
    fn eq(&self, other: &usize) -> bool {
        self.0 == *other as i32
    }
}

impl PartialEq<isize> for Code {
    fn eq(&self, other: &isize) -> bool {
        self.0 == *other as i32
    }
}

impl PartialEq<i32> for Code {
    fn eq(&self, other: &i32) -> bool {
        self.0 == *other
    }
}

#[test]
fn test_code() {
    let c: i32 = Code::new(0).into();
    assert_eq!(c, 0);
    let c = Code::from(0).to_string();
    assert_eq!(c, "0x0000");
    dbg!(Code::from(0x200));

    let c: i8 = Code::new(0).into();
    let mut c: Code = c.into();

    let _: &i32 = &c;
    let _: &mut i32 = &mut c;
}