1use reifydb_value::value::{Value, value_type::ValueType};
5
6use crate::error::{DecodeError, EncodeError};
7
8pub const MAX_OPTION_DEPTH: u8 = 3;
9pub const RESERVED_KIND: u8 = 63;
10pub const EXTENDED_TYPE_TAG: u8 = 0xFF;
11
12#[repr(u8)]
13#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub enum ValueKind {
15 None = 0,
16 Boolean = 1,
17 Float4 = 2,
18 Float8 = 3,
19 Int1 = 4,
20 Int2 = 5,
21 Int4 = 6,
22 Int8 = 7,
23 Int16 = 8,
24 Utf8 = 9,
25 Uint1 = 10,
26 Uint2 = 11,
27 Uint4 = 12,
28 Uint8 = 13,
29 Uint16 = 14,
30 Date = 15,
31 DateTime = 16,
32 Time = 17,
33 Duration = 18,
34 IdentityId = 19,
35 Uuid4 = 20,
36 Uuid7 = 21,
37 Blob = 22,
38 Int = 23,
39 Uint = 24,
40 Decimal = 25,
41 Any = 26,
42 DictionaryId = 27,
43 Type = 28,
44 List = 29,
45 Record = 30,
46 Tuple = 31,
47}
48
49impl ValueKind {
50 pub const ALL: [ValueKind; 32] = [
51 ValueKind::None,
52 ValueKind::Boolean,
53 ValueKind::Float4,
54 ValueKind::Float8,
55 ValueKind::Int1,
56 ValueKind::Int2,
57 ValueKind::Int4,
58 ValueKind::Int8,
59 ValueKind::Int16,
60 ValueKind::Utf8,
61 ValueKind::Uint1,
62 ValueKind::Uint2,
63 ValueKind::Uint4,
64 ValueKind::Uint8,
65 ValueKind::Uint16,
66 ValueKind::Date,
67 ValueKind::DateTime,
68 ValueKind::Time,
69 ValueKind::Duration,
70 ValueKind::IdentityId,
71 ValueKind::Uuid4,
72 ValueKind::Uuid7,
73 ValueKind::Blob,
74 ValueKind::Int,
75 ValueKind::Uint,
76 ValueKind::Decimal,
77 ValueKind::Any,
78 ValueKind::DictionaryId,
79 ValueKind::Type,
80 ValueKind::List,
81 ValueKind::Record,
82 ValueKind::Tuple,
83 ];
84
85 pub const fn byte(self) -> u8 {
86 self as u8
87 }
88
89 pub fn from_byte(byte: u8) -> Option<ValueKind> {
90 if byte < Self::ALL.len() as u8 {
91 Some(Self::ALL[byte as usize])
92 } else {
93 None
94 }
95 }
96
97 pub fn of_value(value: &Value) -> ValueKind {
98 match value {
99 Value::None {
100 ..
101 } => ValueKind::None,
102 Value::Boolean(_) => ValueKind::Boolean,
103 Value::Float4(_) => ValueKind::Float4,
104 Value::Float8(_) => ValueKind::Float8,
105 Value::Int1(_) => ValueKind::Int1,
106 Value::Int2(_) => ValueKind::Int2,
107 Value::Int4(_) => ValueKind::Int4,
108 Value::Int8(_) => ValueKind::Int8,
109 Value::Int16(_) => ValueKind::Int16,
110 Value::Utf8(_) => ValueKind::Utf8,
111 Value::Uint1(_) => ValueKind::Uint1,
112 Value::Uint2(_) => ValueKind::Uint2,
113 Value::Uint4(_) => ValueKind::Uint4,
114 Value::Uint8(_) => ValueKind::Uint8,
115 Value::Uint16(_) => ValueKind::Uint16,
116 Value::Date(_) => ValueKind::Date,
117 Value::DateTime(_) => ValueKind::DateTime,
118 Value::Time(_) => ValueKind::Time,
119 Value::Duration(_) => ValueKind::Duration,
120 Value::IdentityId(_) => ValueKind::IdentityId,
121 Value::Uuid4(_) => ValueKind::Uuid4,
122 Value::Uuid7(_) => ValueKind::Uuid7,
123 Value::Blob(_) => ValueKind::Blob,
124 Value::Int(_) => ValueKind::Int,
125 Value::Uint(_) => ValueKind::Uint,
126 Value::Decimal(_) => ValueKind::Decimal,
127 Value::Any(_) => ValueKind::Any,
128 Value::DictionaryId(_) => ValueKind::DictionaryId,
129 Value::Type(_) => ValueKind::Type,
130 Value::List(_) => ValueKind::List,
131 Value::Record(_) => ValueKind::Record,
132 Value::Tuple(_) => ValueKind::Tuple,
133 }
134 }
135
136 pub fn of_type(ty: &ValueType) -> ValueKind {
137 match ty {
138 ValueType::Option(inner) => Self::of_type(inner),
139 ValueType::Boolean => ValueKind::Boolean,
140 ValueType::Float4 => ValueKind::Float4,
141 ValueType::Float8 => ValueKind::Float8,
142 ValueType::Int1 => ValueKind::Int1,
143 ValueType::Int2 => ValueKind::Int2,
144 ValueType::Int4 => ValueKind::Int4,
145 ValueType::Int8 => ValueKind::Int8,
146 ValueType::Int16 => ValueKind::Int16,
147 ValueType::Utf8 => ValueKind::Utf8,
148 ValueType::Uint1 => ValueKind::Uint1,
149 ValueType::Uint2 => ValueKind::Uint2,
150 ValueType::Uint4 => ValueKind::Uint4,
151 ValueType::Uint8 => ValueKind::Uint8,
152 ValueType::Uint16 => ValueKind::Uint16,
153 ValueType::Date => ValueKind::Date,
154 ValueType::DateTime => ValueKind::DateTime,
155 ValueType::Time => ValueKind::Time,
156 ValueType::Duration => ValueKind::Duration,
157 ValueType::IdentityId => ValueKind::IdentityId,
158 ValueType::Uuid4 => ValueKind::Uuid4,
159 ValueType::Uuid7 => ValueKind::Uuid7,
160 ValueType::Blob => ValueKind::Blob,
161 ValueType::Int => ValueKind::Int,
162 ValueType::Uint => ValueKind::Uint,
163 ValueType::Decimal => ValueKind::Decimal,
164 ValueType::Any => ValueKind::Any,
165 ValueType::DictionaryId => ValueKind::DictionaryId,
166 ValueType::List(_) => ValueKind::List,
167 ValueType::Record(_) => ValueKind::Record,
168 ValueType::Tuple(_) => ValueKind::Tuple,
169 }
170 }
171}
172
173#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
174pub struct TypeTag(u8);
175
176impl TypeTag {
177 pub fn new(kind: ValueKind, depth: u8) -> Result<TypeTag, EncodeError> {
178 if depth > MAX_OPTION_DEPTH {
179 return Err(EncodeError::OptionDepthTooDeep {
180 depth: depth as u32,
181 max: MAX_OPTION_DEPTH,
182 });
183 }
184 Ok(TypeTag((depth << 6) | kind.byte()))
185 }
186
187 pub const fn byte(self) -> u8 {
188 self.0
189 }
190
191 pub const fn depth(self) -> u8 {
192 self.0 >> 6
193 }
194
195 pub const fn kind_bits(self) -> u8 {
196 self.0 & 0x3F
197 }
198
199 pub fn kind(self) -> Option<ValueKind> {
200 ValueKind::from_byte(self.kind_bits())
201 }
202
203 pub fn from_byte(byte: u8) -> Result<TypeTag, DecodeError> {
204 let kind_bits = byte & 0x3F;
205 if kind_bits == RESERVED_KIND {
206 return Err(DecodeError::ReservedTag(byte));
207 }
208 if ValueKind::from_byte(kind_bits).is_none() {
209 return Err(DecodeError::UnknownTypeCode(byte));
210 }
211 let tag = TypeTag(byte);
212 if tag.depth() > 0 && kind_bits == ValueKind::None.byte() {
213 return Err(DecodeError::InvalidData(format!(
214 "tag byte 0x{byte:02X} wraps the none kind in option depth {}",
215 tag.depth()
216 )));
217 }
218 Ok(tag)
219 }
220
221 pub fn of_type(ty: &ValueType) -> Result<TypeTag, EncodeError> {
222 let (base, depth) = peel_options(ty);
223 if depth > MAX_OPTION_DEPTH as u32 {
224 return Err(EncodeError::OptionDepthTooDeep {
225 depth,
226 max: MAX_OPTION_DEPTH,
227 });
228 }
229 Self::new(ValueKind::of_type(base), depth as u8)
230 }
231
232 pub fn to_type(self) -> Result<ValueType, DecodeError> {
233 let base = match self.kind().ok_or(DecodeError::UnknownTypeCode(self.0))? {
234 ValueKind::None | ValueKind::Type => {
235 return Err(DecodeError::UnsupportedType(format!(
236 "kind {:?} has no standalone value type",
237 self.kind()
238 )));
239 }
240 ValueKind::Boolean => ValueType::Boolean,
241 ValueKind::Float4 => ValueType::Float4,
242 ValueKind::Float8 => ValueType::Float8,
243 ValueKind::Int1 => ValueType::Int1,
244 ValueKind::Int2 => ValueType::Int2,
245 ValueKind::Int4 => ValueType::Int4,
246 ValueKind::Int8 => ValueType::Int8,
247 ValueKind::Int16 => ValueType::Int16,
248 ValueKind::Utf8 => ValueType::Utf8,
249 ValueKind::Uint1 => ValueType::Uint1,
250 ValueKind::Uint2 => ValueType::Uint2,
251 ValueKind::Uint4 => ValueType::Uint4,
252 ValueKind::Uint8 => ValueType::Uint8,
253 ValueKind::Uint16 => ValueType::Uint16,
254 ValueKind::Date => ValueType::Date,
255 ValueKind::DateTime => ValueType::DateTime,
256 ValueKind::Time => ValueType::Time,
257 ValueKind::Duration => ValueType::Duration,
258 ValueKind::IdentityId => ValueType::IdentityId,
259 ValueKind::Uuid4 => ValueType::Uuid4,
260 ValueKind::Uuid7 => ValueType::Uuid7,
261 ValueKind::Blob => ValueType::Blob,
262 ValueKind::Int => ValueType::Int,
263 ValueKind::Uint => ValueType::Uint,
264 ValueKind::Decimal => ValueType::Decimal,
265 ValueKind::Any => ValueType::Any,
266 ValueKind::DictionaryId => ValueType::DictionaryId,
267 ValueKind::List => ValueType::List(Box::new(ValueType::Any)),
268 ValueKind::Record => ValueType::Record(Vec::new()),
269 ValueKind::Tuple => ValueType::Tuple(Vec::new()),
270 };
271 Ok((0..self.depth()).fold(base, |ty, _| ValueType::Option(Box::new(ty))))
272 }
273}
274
275pub(crate) fn peel_options(ty: &ValueType) -> (&ValueType, u32) {
276 let mut depth = 0u32;
277 let mut base = ty;
278 while let ValueType::Option(inner) = base {
279 depth += 1;
280 base = inner;
281 }
282 (base, depth)
283}
284
285pub fn type_tag_byte(ty: &ValueType) -> u8 {
286 TypeTag::of_type(ty).expect("option nesting exceeds the type tag capacity").byte()
287}
288
289pub fn value_type_from_tag_byte(byte: u8) -> ValueType {
290 TypeTag::from_byte(byte).and_then(TypeTag::to_type).expect("invalid persisted type tag byte")
291}