Skip to main content

regulus_db/types/
value.rs

1use std::fmt;
2use std::cmp::Ordering;
3use std::hash::{Hash, Hasher};
4use serde::{Serialize, Deserialize};
5
6/// 数据库值类型 - 支持 8 种基本类型
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub enum DbValue {
9    Null,
10    Integer(i64),
11    Real(f64),
12    Text(String),
13    Blob(Vec<u8>),
14    Boolean(bool),
15    Date(i64),      // Unix 时间戳(天)
16    Datetime(i64),  // Unix 时间戳(毫秒)
17}
18
19impl Hash for DbValue {
20    fn hash<H: Hasher>(&self, state: &mut H) {
21        // 先哈希类型标签
22        match self {
23            DbValue::Null => 0u8.hash(state),
24            DbValue::Integer(_) => 1u8.hash(state),
25            DbValue::Real(_) => 2u8.hash(state),
26            DbValue::Text(_) => 3u8.hash(state),
27            DbValue::Blob(_) => 4u8.hash(state),
28            DbValue::Boolean(_) => 5u8.hash(state),
29            DbValue::Date(_) => 6u8.hash(state),
30            DbValue::Datetime(_) => 7u8.hash(state),
31        }
32        // 再哈希具体值
33        match self {
34            DbValue::Null => {}
35            DbValue::Integer(v) => v.hash(state),
36            DbValue::Real(v) => v.to_bits().hash(state),
37            DbValue::Text(v) => v.hash(state),
38            DbValue::Blob(v) => v.hash(state),
39            DbValue::Boolean(v) => v.hash(state),
40            DbValue::Date(v) => v.hash(state),
41            DbValue::Datetime(v) => v.hash(state),
42        }
43    }
44}
45
46impl PartialOrd for DbValue {
47    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
48        Some(self.cmp(other))
49    }
50}
51
52impl Ord for DbValue {
53    fn cmp(&self, other: &Self) -> Ordering {
54        // 首先按类型排序
55        let self_type_order = self.type_order();
56        let other_type_order = other.type_order();
57
58        match self_type_order.cmp(&other_type_order) {
59            Ordering::Equal => {
60                // 同类型之间比较
61                match (self, other) {
62                    (DbValue::Null, DbValue::Null) => Ordering::Equal,
63                    (DbValue::Integer(a), DbValue::Integer(b)) => a.cmp(b),
64                    (DbValue::Real(a), DbValue::Real(b)) => a.partial_cmp(b).unwrap_or(Ordering::Equal),
65                    (DbValue::Text(a), DbValue::Text(b)) => a.cmp(b),
66                    (DbValue::Blob(a), DbValue::Blob(b)) => a.cmp(b),
67                    (DbValue::Boolean(a), DbValue::Boolean(b)) => a.cmp(b),
68                    (DbValue::Date(a), DbValue::Date(b)) => a.cmp(b),
69                    (DbValue::Datetime(a), DbValue::Datetime(b)) => a.cmp(b),
70                    _ => Ordering::Equal,
71                }
72            }
73            other_order => other_order,
74        }
75    }
76}
77
78impl Eq for DbValue {}
79
80impl DbValue {
81    /// 返回类型的顺序(用于 Ord 实现)
82    fn type_order(&self) -> u8 {
83        match self {
84            DbValue::Null => 0,
85            DbValue::Integer(_) => 1,
86            DbValue::Real(_) => 2,
87            DbValue::Text(_) => 3,
88            DbValue::Blob(_) => 4,
89            DbValue::Boolean(_) => 5,
90            DbValue::Date(_) => 6,
91            DbValue::Datetime(_) => 7,
92        }
93    }
94    // 构造函数
95    pub fn null() -> Self {
96        DbValue::Null
97    }
98
99    pub fn integer(v: i64) -> Self {
100        DbValue::Integer(v)
101    }
102
103    pub fn real(v: f64) -> Self {
104        DbValue::Real(v)
105    }
106
107    pub fn text(v: impl Into<String>) -> Self {
108        DbValue::Text(v.into())
109    }
110
111    pub fn blob(v: Vec<u8>) -> Self {
112        DbValue::Blob(v)
113    }
114
115    pub fn boolean(v: bool) -> Self {
116        DbValue::Boolean(v)
117    }
118
119    pub fn date(v: i64) -> Self {
120        DbValue::Date(v)
121    }
122
123    pub fn datetime(v: i64) -> Self {
124        DbValue::Datetime(v)
125    }
126
127    // 类型转换方法
128    pub fn as_integer(&self) -> Option<i64> {
129        match self {
130            DbValue::Integer(v) => Some(*v),
131            _ => None,
132        }
133    }
134
135    pub fn as_real(&self) -> Option<f64> {
136        match self {
137            DbValue::Real(v) => Some(*v),
138            DbValue::Integer(v) => Some(*v as f64),
139            _ => None,
140        }
141    }
142
143    pub fn as_text(&self) -> Option<&str> {
144        match self {
145            DbValue::Text(s) => Some(s),
146            _ => None,
147        }
148    }
149
150    pub fn as_blob(&self) -> Option<&[u8]> {
151        match self {
152            DbValue::Blob(b) => Some(b),
153            _ => None,
154        }
155    }
156
157    pub fn as_boolean(&self) -> Option<bool> {
158        match self {
159            DbValue::Boolean(v) => Some(*v),
160            _ => None,
161        }
162    }
163
164    pub fn as_date(&self) -> Option<i64> {
165        match self {
166            DbValue::Date(v) => Some(*v),
167            _ => None,
168        }
169    }
170
171    pub fn as_datetime(&self) -> Option<i64> {
172        match self {
173            DbValue::Datetime(v) => Some(*v),
174            _ => None,
175        }
176    }
177
178    // 判断是否为 Null
179    pub fn is_null(&self) -> bool {
180        matches!(self, DbValue::Null)
181    }
182
183    // 获取类型名称
184    pub fn type_name(&self) -> &'static str {
185        match self {
186            DbValue::Null => "NULL",
187            DbValue::Integer(_) => "INTEGER",
188            DbValue::Real(_) => "REAL",
189            DbValue::Text(_) => "TEXT",
190            DbValue::Blob(_) => "BLOB",
191            DbValue::Boolean(_) => "BOOLEAN",
192            DbValue::Date(_) => "DATE",
193            DbValue::Datetime(_) => "DATETIME",
194        }
195    }
196}
197
198impl fmt::Display for DbValue {
199    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200        match self {
201            DbValue::Null => write!(f, "NULL"),
202            DbValue::Integer(v) => write!(f, "{}", v),
203            DbValue::Real(v) => write!(f, "{}", v),
204            DbValue::Text(s) => write!(f, "'{}'", s),
205            DbValue::Blob(b) => write!(f, "X'{}'", hex::encode(b)),
206            DbValue::Boolean(v) => write!(f, "{}", if *v { "TRUE" } else { "FALSE" }),
207            DbValue::Date(v) => write!(f, "DATE({})", v),
208            DbValue::Datetime(v) => write!(f, "DATETIME({})", v),
209        }
210    }
211}
212
213// 简单的 hex 编码辅助函数(避免依赖)
214mod hex {
215    pub fn encode(data: &[u8]) -> String {
216        data.iter().map(|b| format!("{:02X}", b)).collect()
217    }
218}
219
220#[cfg(test)]
221mod tests {
222    use super::*;
223
224    #[test]
225    fn test_integer_conversion() {
226        let v = DbValue::integer(42);
227        assert_eq!(v.as_integer(), Some(42));
228        assert_eq!(v.as_real(), Some(42.0));
229        assert_eq!(v.as_boolean(), None);
230    }
231
232    #[test]
233    fn test_text_conversion() {
234        let v = DbValue::text("hello");
235        assert_eq!(v.as_text(), Some("hello"));
236        assert_eq!(v.as_integer(), None);
237    }
238
239    #[test]
240    fn test_boolean_conversion() {
241        let v = DbValue::boolean(true);
242        assert_eq!(v.as_boolean(), Some(true));
243    }
244
245    #[test]
246    fn test_null() {
247        let v = DbValue::null();
248        assert!(v.is_null());
249        assert_eq!(v.as_integer(), None);
250    }
251}