1use serde::{Deserialize, Serialize};
4
5use crate::dbms::value::Value;
6use crate::memory::Encode;
7
8mod blob;
9mod boolean;
10mod date;
11mod datetime;
12mod decimal;
13mod integers;
14mod json;
15mod nullable;
16mod text;
17mod uuid;
18
19pub use self::blob::Blob;
20pub use self::boolean::Boolean;
21pub use self::date::Date;
22pub use self::datetime::DateTime;
23pub use self::decimal::Decimal;
24pub use self::integers::{Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64};
25pub use self::json::Json;
26pub use self::nullable::Nullable;
27pub use self::text::Text;
28pub use self::uuid::Uuid;
29
30pub trait DataType:
38 Clone
39 + std::fmt::Debug
40 + std::fmt::Display
41 + PartialEq
42 + Eq
43 + Default
44 + PartialOrd
45 + Ord
46 + std::hash::Hash
47 + Encode
48 + Serialize
49 + Into<Value>
50 + for<'de> Deserialize<'de>
51{
52}
53
54pub trait CustomDataType: DataType {
67 const TYPE_TAG: &'static str;
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
73pub enum DataTypeKind {
74 Blob,
75 Boolean,
76 Date,
77 DateTime,
78 Decimal,
79 Int8,
80 Int16,
81 Int32,
82 Int64,
83 Json,
84 Text,
85 Uint8,
86 Uint16,
87 Uint32,
88 Uint64,
89 Uuid,
90 Custom {
94 tag: &'static str,
95 wire_size: crate::dbms::table::WireSize,
96 },
97}
98
99#[cfg(test)]
100mod test {
101
102 use std::collections::HashSet;
103
104 use super::*;
105
106 #[test]
107 fn test_should_create_all_data_type_kind_variants() {
108 let kinds = [
109 DataTypeKind::Blob,
110 DataTypeKind::Boolean,
111 DataTypeKind::Date,
112 DataTypeKind::DateTime,
113 DataTypeKind::Decimal,
114 DataTypeKind::Int8,
115 DataTypeKind::Int16,
116 DataTypeKind::Int32,
117 DataTypeKind::Int64,
118 DataTypeKind::Json,
119 DataTypeKind::Text,
120 DataTypeKind::Uint8,
121 DataTypeKind::Uint16,
122 DataTypeKind::Uint32,
123 DataTypeKind::Uint64,
124 DataTypeKind::Uuid,
125 ];
126
127 assert_eq!(kinds.len(), 16);
128 }
129
130 #[test]
131 #[allow(clippy::clone_on_copy)]
132 fn test_should_clone_data_type_kind() {
133 let kind = DataTypeKind::Text;
134 let cloned = kind.clone();
135 assert_eq!(kind, cloned);
136 }
137
138 #[test]
139 fn test_should_copy_data_type_kind() {
140 let kind = DataTypeKind::Uint32;
141 let copied = kind;
142 assert_eq!(kind, copied);
143 }
144
145 #[test]
146 fn test_should_compare_data_type_kinds() {
147 assert_eq!(DataTypeKind::Blob, DataTypeKind::Blob);
148 assert_eq!(DataTypeKind::Boolean, DataTypeKind::Boolean);
149 assert_ne!(DataTypeKind::Blob, DataTypeKind::Boolean);
150 assert_ne!(DataTypeKind::Int32, DataTypeKind::Int64);
151 assert_ne!(DataTypeKind::Uint32, DataTypeKind::Uint64);
152 }
153
154 #[test]
155 fn test_should_hash_data_type_kind() {
156 let mut set = HashSet::new();
157 set.insert(DataTypeKind::Text);
158 set.insert(DataTypeKind::Uint32);
159 set.insert(DataTypeKind::Boolean);
160
161 assert!(set.contains(&DataTypeKind::Text));
162 assert!(set.contains(&DataTypeKind::Uint32));
163 assert!(set.contains(&DataTypeKind::Boolean));
164 assert!(!set.contains(&DataTypeKind::Blob));
165 }
166
167 #[test]
168 fn test_should_debug_data_type_kind() {
169 assert_eq!(format!("{:?}", DataTypeKind::Blob), "Blob");
170 assert_eq!(format!("{:?}", DataTypeKind::Boolean), "Boolean");
171 assert_eq!(format!("{:?}", DataTypeKind::Date), "Date");
172 assert_eq!(format!("{:?}", DataTypeKind::DateTime), "DateTime");
173 assert_eq!(format!("{:?}", DataTypeKind::Decimal), "Decimal");
174 assert_eq!(format!("{:?}", DataTypeKind::Int8), "Int8");
175 assert_eq!(format!("{:?}", DataTypeKind::Int16), "Int16");
176 assert_eq!(format!("{:?}", DataTypeKind::Int32), "Int32");
177 assert_eq!(format!("{:?}", DataTypeKind::Int64), "Int64");
178 assert_eq!(format!("{:?}", DataTypeKind::Json), "Json");
179 assert_eq!(format!("{:?}", DataTypeKind::Text), "Text");
180 assert_eq!(format!("{:?}", DataTypeKind::Uint8), "Uint8");
181 assert_eq!(format!("{:?}", DataTypeKind::Uint16), "Uint16");
182 assert_eq!(format!("{:?}", DataTypeKind::Uint32), "Uint32");
183 assert_eq!(format!("{:?}", DataTypeKind::Uint64), "Uint64");
184 assert_eq!(format!("{:?}", DataTypeKind::Uuid), "Uuid");
185 }
186
187 #[test]
188 fn test_should_use_data_type_kind_as_hashmap_key() {
189 use std::collections::HashMap;
190
191 let mut map = HashMap::new();
192 map.insert(DataTypeKind::Text, "String type");
193 map.insert(DataTypeKind::Uint32, "32-bit unsigned integer");
194
195 assert_eq!(map.get(&DataTypeKind::Text), Some(&"String type"));
196 assert_eq!(
197 map.get(&DataTypeKind::Uint32),
198 Some(&"32-bit unsigned integer")
199 );
200 assert_eq!(map.get(&DataTypeKind::Blob), None);
201 }
202
203 #[test]
204 fn test_should_create_custom_data_type_kind() {
205 use crate::dbms::table::WireSize;
206 let kind = DataTypeKind::Custom {
207 tag: "role",
208 wire_size: WireSize::Fixed(1),
209 };
210 assert_eq!(
211 kind,
212 DataTypeKind::Custom {
213 tag: "role",
214 wire_size: WireSize::Fixed(1)
215 }
216 );
217 assert_ne!(
218 kind,
219 DataTypeKind::Custom {
220 tag: "status",
221 wire_size: WireSize::Fixed(1)
222 }
223 );
224 assert_ne!(kind, DataTypeKind::Text);
225 }
226
227 #[test]
228 fn test_should_copy_custom_data_type_kind() {
229 use crate::dbms::table::WireSize;
230 let kind = DataTypeKind::Custom {
231 tag: "role",
232 wire_size: WireSize::LengthPrefixed,
233 };
234 let copied = kind;
235 assert_eq!(kind, copied);
236 }
237
238 #[test]
239 fn test_should_debug_custom_data_type_kind() {
240 use crate::dbms::table::WireSize;
241 let kind = DataTypeKind::Custom {
242 tag: "role",
243 wire_size: WireSize::Fixed(1),
244 };
245 let debug = format!("{kind:?}");
246 assert!(debug.contains("Custom"));
247 assert!(debug.contains("role"));
248 }
249}