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 Decimal = 23,
39 Any = 24,
40 DictionaryId = 25,
41 Type = 26,
42 List = 27,
43 Record = 28,
44 Tuple = 29,
45 Digest = 30,
46 Enum = 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::Decimal,
75 ValueKind::Any,
76 ValueKind::DictionaryId,
77 ValueKind::Type,
78 ValueKind::List,
79 ValueKind::Record,
80 ValueKind::Tuple,
81 ValueKind::Digest,
82 ValueKind::Enum,
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::Enum(_) => ValueKind::Enum,
112 Value::Uint1(_) => ValueKind::Uint1,
113 Value::Uint2(_) => ValueKind::Uint2,
114 Value::Uint4(_) => ValueKind::Uint4,
115 Value::Uint8(_) => ValueKind::Uint8,
116 Value::Uint16(_) => ValueKind::Uint16,
117 Value::Date(_) => ValueKind::Date,
118 Value::DateTime(_) => ValueKind::DateTime,
119 Value::Time(_) => ValueKind::Time,
120 Value::Duration(_) => ValueKind::Duration,
121 Value::IdentityId(_) => ValueKind::IdentityId,
122 Value::Uuid4(_) => ValueKind::Uuid4,
123 Value::Uuid7(_) => ValueKind::Uuid7,
124 Value::Blob(_) => ValueKind::Blob,
125 Value::Decimal(_) => ValueKind::Decimal,
126 Value::Any(_) => ValueKind::Any,
127 Value::DictionaryId(_) => ValueKind::DictionaryId,
128 Value::Type(_) => ValueKind::Type,
129 Value::List(_) => ValueKind::List,
130 Value::Record(_) => ValueKind::Record,
131 Value::Tuple(_) => ValueKind::Tuple,
132 Value::Digest(_) => ValueKind::Digest,
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::Enum(_) => ValueKind::Enum,
149 ValueType::Uint1 => ValueKind::Uint1,
150 ValueType::Uint2 => ValueKind::Uint2,
151 ValueType::Uint4 => ValueKind::Uint4,
152 ValueType::Uint8 => ValueKind::Uint8,
153 ValueType::Uint16 => ValueKind::Uint16,
154 ValueType::Date => ValueKind::Date,
155 ValueType::DateTime => ValueKind::DateTime,
156 ValueType::Time => ValueKind::Time,
157 ValueType::Duration => ValueKind::Duration,
158 ValueType::IdentityId => ValueKind::IdentityId,
159 ValueType::Uuid4 => ValueKind::Uuid4,
160 ValueType::Uuid7 => ValueKind::Uuid7,
161 ValueType::Blob => ValueKind::Blob,
162 ValueType::Decimal {
163 ..
164 } => ValueKind::Decimal,
165 ValueType::Any => ValueKind::Any,
166 ValueType::DictionaryId => ValueKind::DictionaryId,
167 ValueType::List(_) => ValueKind::List,
168 ValueType::Record(_) => ValueKind::Record,
169 ValueType::Tuple(_) => ValueKind::Tuple,
170 ValueType::Digest {
171 ..
172 } => ValueKind::Digest,
173 }
174 }
175}
176
177#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
178pub struct TypeTag(u8);
179
180impl TypeTag {
181 pub fn new(kind: ValueKind, depth: u8) -> Result<TypeTag, EncodeError> {
182 if depth > MAX_OPTION_DEPTH {
183 return Err(EncodeError::OptionDepthTooDeep {
184 depth: depth as u32,
185 max: MAX_OPTION_DEPTH,
186 });
187 }
188 Ok(TypeTag((depth << 6) | kind.byte()))
189 }
190
191 pub const fn byte(self) -> u8 {
192 self.0
193 }
194
195 pub const fn depth(self) -> u8 {
196 self.0 >> 6
197 }
198
199 pub const fn kind_bits(self) -> u8 {
200 self.0 & 0x3F
201 }
202
203 pub fn kind(self) -> Option<ValueKind> {
204 ValueKind::from_byte(self.kind_bits())
205 }
206
207 pub fn from_byte(byte: u8) -> Result<TypeTag, DecodeError> {
208 let kind_bits = byte & 0x3F;
209 if kind_bits == RESERVED_KIND {
210 return Err(DecodeError::ReservedTag(byte));
211 }
212 if ValueKind::from_byte(kind_bits).is_none() {
213 return Err(DecodeError::UnknownTypeCode(byte));
214 }
215 let tag = TypeTag(byte);
216 if tag.depth() > 0 && kind_bits == ValueKind::None.byte() {
217 return Err(DecodeError::InvalidData(format!(
218 "tag byte 0x{byte:02X} wraps the none kind in option depth {}",
219 tag.depth()
220 )));
221 }
222 Ok(tag)
223 }
224
225 pub fn of_type(ty: &ValueType) -> Result<TypeTag, EncodeError> {
226 let (base, depth) = peel_options(ty);
227 if depth > MAX_OPTION_DEPTH as u32 {
228 return Err(EncodeError::OptionDepthTooDeep {
229 depth,
230 max: MAX_OPTION_DEPTH,
231 });
232 }
233 Self::new(ValueKind::of_type(base), depth as u8)
234 }
235
236 pub fn to_type(self) -> Result<ValueType, DecodeError> {
237 let base = match self.kind().ok_or(DecodeError::UnknownTypeCode(self.0))? {
238 ValueKind::None | ValueKind::Type => {
239 return Err(DecodeError::UnsupportedType(format!(
240 "kind {:?} has no standalone value type",
241 self.kind()
242 )));
243 }
244 ValueKind::Enum => {
245 return Err(DecodeError::UnsupportedType(
246 "kind Enum needs its sumtype, which a type tag does not carry".to_string(),
247 ));
248 }
249 ValueKind::Digest => {
250 return Err(DecodeError::UnsupportedType(
251 "kind Digest needs its inner type and accuracy, which a type tag does not carry"
252 .to_string(),
253 ));
254 }
255 ValueKind::Boolean => ValueType::Boolean,
256 ValueKind::Float4 => ValueType::Float4,
257 ValueKind::Float8 => ValueType::Float8,
258 ValueKind::Int1 => ValueType::Int1,
259 ValueKind::Int2 => ValueType::Int2,
260 ValueKind::Int4 => ValueType::Int4,
261 ValueKind::Int8 => ValueType::Int8,
262 ValueKind::Int16 => ValueType::Int16,
263 ValueKind::Utf8 => ValueType::Utf8,
264 ValueKind::Uint1 => ValueType::Uint1,
265 ValueKind::Uint2 => ValueType::Uint2,
266 ValueKind::Uint4 => ValueType::Uint4,
267 ValueKind::Uint8 => ValueType::Uint8,
268 ValueKind::Uint16 => ValueType::Uint16,
269 ValueKind::Date => ValueType::Date,
270 ValueKind::DateTime => ValueType::DateTime,
271 ValueKind::Time => ValueType::Time,
272 ValueKind::Duration => ValueType::Duration,
273 ValueKind::IdentityId => ValueType::IdentityId,
274 ValueKind::Uuid4 => ValueType::Uuid4,
275 ValueKind::Uuid7 => ValueType::Uuid7,
276 ValueKind::Blob => ValueType::Blob,
277 ValueKind::Decimal => ValueType::DECIMAL,
278 ValueKind::Any => ValueType::Any,
279 ValueKind::DictionaryId => ValueType::DictionaryId,
280 ValueKind::List => ValueType::List(Box::new(ValueType::Any)),
281 ValueKind::Record => ValueType::Record(Vec::new()),
282 ValueKind::Tuple => ValueType::Tuple(Vec::new()),
283 };
284 Ok((0..self.depth()).fold(base, |ty, _| ValueType::Option(Box::new(ty))))
285 }
286}
287
288pub(crate) fn peel_options(ty: &ValueType) -> (&ValueType, u32) {
289 let mut depth = 0u32;
290 let mut base = ty;
291 while let ValueType::Option(inner) = base {
292 depth += 1;
293 base = inner;
294 }
295 (base, depth)
296}
297
298pub fn value_type_from_tag_byte(byte: u8) -> ValueType {
299 TypeTag::from_byte(byte).and_then(TypeTag::to_type).expect("invalid persisted type tag byte")
300}