1use crate::error::{Result, fmt};
31
32#[repr(u8)]
38#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
39#[non_exhaustive]
40pub enum ColumnKind {
41 Boolean = 0x01,
42 Byte = 0x02,
43 Short = 0x03,
44 Int = 0x04,
45 Long = 0x05,
46 Float = 0x06,
47 Double = 0x07,
48 Symbol = 0x09,
50 Timestamp = 0x0A,
52 Date = 0x0B,
53 Uuid = 0x0C,
54 Long256 = 0x0D,
55 Geohash = 0x0E,
56 Varchar = 0x0F,
57 TimestampNanos = 0x10,
59 DoubleArray = 0x11,
60 LongArray = 0x12,
61 Decimal64 = 0x13,
62 Decimal128 = 0x14,
63 Decimal256 = 0x15,
64 Char = 0x16,
65 Binary = 0x17,
66 Ipv4 = 0x18,
67}
68
69impl ColumnKind {
70 pub fn from_u8(byte: u8) -> Result<Self> {
72 Ok(match byte {
73 0x01 => ColumnKind::Boolean,
74 0x02 => ColumnKind::Byte,
75 0x03 => ColumnKind::Short,
76 0x04 => ColumnKind::Int,
77 0x05 => ColumnKind::Long,
78 0x06 => ColumnKind::Float,
79 0x07 => ColumnKind::Double,
80 0x09 => ColumnKind::Symbol,
81 0x0A => ColumnKind::Timestamp,
82 0x0B => ColumnKind::Date,
83 0x0C => ColumnKind::Uuid,
84 0x0D => ColumnKind::Long256,
85 0x0E => ColumnKind::Geohash,
86 0x0F => ColumnKind::Varchar,
87 0x10 => ColumnKind::TimestampNanos,
88 0x11 => ColumnKind::DoubleArray,
89 0x12 => ColumnKind::LongArray,
90 0x13 => ColumnKind::Decimal64,
91 0x14 => ColumnKind::Decimal128,
92 0x15 => ColumnKind::Decimal256,
93 0x16 => ColumnKind::Char,
94 0x17 => ColumnKind::Binary,
95 0x18 => ColumnKind::Ipv4,
96 0x08 => {
97 return Err(fmt!(
98 ProtocolError,
99 "type code 0x08 is reserved (was STRING)"
100 ));
101 }
102 other => {
103 return Err(fmt!(
104 ProtocolError,
105 "unknown column type code 0x{:02X}",
106 other
107 ));
108 }
109 })
110 }
111
112 pub fn as_u8(self) -> u8 {
113 self as u8
114 }
115
116 pub fn name(self) -> &'static str {
118 match self {
119 ColumnKind::Boolean => "boolean",
120 ColumnKind::Byte => "byte",
121 ColumnKind::Short => "short",
122 ColumnKind::Int => "int",
123 ColumnKind::Long => "long",
124 ColumnKind::Float => "float",
125 ColumnKind::Double => "double",
126 ColumnKind::Symbol => "symbol",
127 ColumnKind::Timestamp => "timestamp",
128 ColumnKind::Date => "date",
129 ColumnKind::Uuid => "uuid",
130 ColumnKind::Long256 => "long256",
131 ColumnKind::Geohash => "geohash",
132 ColumnKind::Varchar => "varchar",
133 ColumnKind::TimestampNanos => "timestamp_nanos",
134 ColumnKind::DoubleArray => "double_array",
135 ColumnKind::LongArray => "long_array",
136 ColumnKind::Decimal64 => "decimal64",
137 ColumnKind::Decimal128 => "decimal128",
138 ColumnKind::Decimal256 => "decimal256",
139 ColumnKind::Char => "char",
140 ColumnKind::Binary => "binary",
141 ColumnKind::Ipv4 => "ipv4",
142 }
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 const ALL: &[ColumnKind] = &[
151 ColumnKind::Boolean,
152 ColumnKind::Byte,
153 ColumnKind::Short,
154 ColumnKind::Int,
155 ColumnKind::Long,
156 ColumnKind::Float,
157 ColumnKind::Double,
158 ColumnKind::Symbol,
159 ColumnKind::Timestamp,
160 ColumnKind::Date,
161 ColumnKind::Uuid,
162 ColumnKind::Long256,
163 ColumnKind::Geohash,
164 ColumnKind::Varchar,
165 ColumnKind::TimestampNanos,
166 ColumnKind::DoubleArray,
167 ColumnKind::LongArray,
168 ColumnKind::Decimal64,
169 ColumnKind::Decimal128,
170 ColumnKind::Decimal256,
171 ColumnKind::Char,
172 ColumnKind::Binary,
173 ColumnKind::Ipv4,
174 ];
175
176 #[test]
177 fn roundtrip_all_known_codes() {
178 for &k in ALL {
179 assert_eq!(ColumnKind::from_u8(k.as_u8()).unwrap(), k, "{}", k.name());
180 }
181 }
182
183 #[test]
184 fn reserved_string_code_rejected() {
185 assert!(ColumnKind::from_u8(0x08).is_err());
186 }
187
188 #[test]
189 fn unknown_codes_rejected() {
190 assert!(ColumnKind::from_u8(0x00).is_err());
191 assert!(ColumnKind::from_u8(0x19).is_err());
192 assert!(ColumnKind::from_u8(0xFF).is_err());
193 }
194
195 #[test]
196 fn names_unique() {
197 let names: Vec<_> = ALL.iter().map(|k| k.name()).collect();
198 let mut sorted = names.clone();
199 sorted.sort_unstable();
200 sorted.dedup();
201 assert_eq!(names.len(), sorted.len());
202 }
203}