1use std::{collections::HashMap, str::from_utf8};
5
6use bigdecimal::BigDecimal;
7use num_bigint::BigInt;
8use reifydb_value::{
9 params::Params,
10 value::{
11 Value,
12 blob::Blob,
13 date::Date,
14 datetime::DateTime,
15 decimal::Decimal,
16 dictionary::DictionaryEntryId,
17 duration::Duration,
18 identity::IdentityId,
19 int::Int,
20 ordered_f32::OrderedF32,
21 ordered_f64::OrderedF64,
22 time::Time,
23 uint::Uint,
24 uuid::{Uuid4, Uuid7},
25 },
26};
27use uuid::Uuid;
28
29use crate::{
30 error::{DecodeError, EncodeError},
31 reader::Reader,
32 tag::ValueKind,
33 typeinfo::{decode_value_type, encode_value_type},
34};
35
36pub fn encode_value(value: &Value) -> Result<Vec<u8>, EncodeError> {
37 let mut buf = Vec::new();
38 encode_value_into(value, &mut buf)?;
39 Ok(buf)
40}
41
42pub fn encode_value_into(value: &Value, buf: &mut Vec<u8>) -> Result<(), EncodeError> {
43 buf.push(ValueKind::of_value(value).byte());
44 match value {
45 Value::None {
46 inner,
47 } => encode_value_type(inner, buf)?,
48 Value::Boolean(b) => buf.push(*b as u8),
49 Value::Float4(f) => buf.extend_from_slice(&f.to_le_bytes()),
50 Value::Float8(f) => buf.extend_from_slice(&f.to_le_bytes()),
51 Value::Int1(v) => buf.extend_from_slice(&v.to_le_bytes()),
52 Value::Int2(v) => buf.extend_from_slice(&v.to_le_bytes()),
53 Value::Int4(v) => buf.extend_from_slice(&v.to_le_bytes()),
54 Value::Int8(v) => buf.extend_from_slice(&v.to_le_bytes()),
55 Value::Int16(v) => buf.extend_from_slice(&v.to_le_bytes()),
56 Value::Utf8(s) => encode_len_prefixed(s.as_bytes(), buf),
57 Value::Uint1(v) => buf.extend_from_slice(&v.to_le_bytes()),
58 Value::Uint2(v) => buf.extend_from_slice(&v.to_le_bytes()),
59 Value::Uint4(v) => buf.extend_from_slice(&v.to_le_bytes()),
60 Value::Uint8(v) => buf.extend_from_slice(&v.to_le_bytes()),
61 Value::Uint16(v) => buf.extend_from_slice(&v.to_le_bytes()),
62 Value::Date(d) => buf.extend_from_slice(&d.to_days_since_epoch().to_le_bytes()),
63 Value::DateTime(dt) => buf.extend_from_slice(&dt.to_nanos().to_le_bytes()),
64 Value::Time(t) => buf.extend_from_slice(&t.to_nanos_since_midnight().to_le_bytes()),
65 Value::Duration(d) => {
66 buf.extend_from_slice(&d.get_months().to_le_bytes());
67 buf.extend_from_slice(&d.get_days().to_le_bytes());
68 buf.extend_from_slice(&d.get_nanos().to_le_bytes());
69 }
70 Value::IdentityId(id) => buf.extend_from_slice(id.0.0.as_bytes()),
71 Value::Uuid4(u) => buf.extend_from_slice(u.0.as_bytes()),
72 Value::Uuid7(u) => buf.extend_from_slice(u.0.as_bytes()),
73 Value::Blob(b) => encode_len_prefixed(b.as_bytes(), buf),
74 Value::Int(v) => encode_len_prefixed(&v.0.to_signed_bytes_le(), buf),
75 Value::Uint(v) => encode_len_prefixed(&v.0.to_signed_bytes_le(), buf),
76 Value::Decimal(v) => encode_len_prefixed(v.to_string().as_bytes(), buf),
77 Value::Any(inner) => encode_value_into(inner, buf)?,
78 Value::DictionaryId(id) => match id {
79 DictionaryEntryId::U1(v) => {
80 buf.push(1);
81 buf.extend_from_slice(&v.to_le_bytes());
82 }
83 DictionaryEntryId::U2(v) => {
84 buf.push(2);
85 buf.extend_from_slice(&v.to_le_bytes());
86 }
87 DictionaryEntryId::U4(v) => {
88 buf.push(4);
89 buf.extend_from_slice(&v.to_le_bytes());
90 }
91 DictionaryEntryId::U8(v) => {
92 buf.push(8);
93 buf.extend_from_slice(&v.to_le_bytes());
94 }
95 DictionaryEntryId::U16(v) => {
96 buf.push(16);
97 buf.extend_from_slice(&v.to_le_bytes());
98 }
99 },
100 Value::Type(ty) => encode_value_type(ty, buf)?,
101 Value::List(items) | Value::Tuple(items) => {
102 buf.extend_from_slice(&(items.len() as u32).to_le_bytes());
103 for item in items {
104 encode_value_into(item, buf)?;
105 }
106 }
107 Value::Record(fields) => {
108 buf.extend_from_slice(&(fields.len() as u32).to_le_bytes());
109 for (key, field_value) in fields {
110 encode_len_prefixed(key.as_bytes(), buf);
111 encode_value_into(field_value, buf)?;
112 }
113 }
114 }
115 Ok(())
116}
117
118fn encode_len_prefixed(bytes: &[u8], buf: &mut Vec<u8>) {
119 buf.extend_from_slice(&(bytes.len() as u32).to_le_bytes());
120 buf.extend_from_slice(bytes);
121}
122
123pub fn decode_value(bytes: &[u8]) -> Result<Value, DecodeError> {
124 let mut r = Reader::new(bytes);
125 let value = decode_value_from(&mut r)?;
126 if !r.is_empty() {
127 return Err(DecodeError::TrailingBytes(r.remaining()));
128 }
129 Ok(value)
130}
131
132pub fn decode_value_from(r: &mut Reader) -> Result<Value, DecodeError> {
133 let byte = r.u8()?;
134 let kind = ValueKind::from_byte(byte).ok_or(DecodeError::UnknownTypeCode(byte))?;
135 match kind {
136 ValueKind::None => Ok(Value::None {
137 inner: decode_value_type(r)?,
138 }),
139 ValueKind::Boolean => Ok(Value::Boolean(r.u8()? != 0)),
140 ValueKind::Float4 => OrderedF32::try_from(r.f32()?)
141 .map(Value::Float4)
142 .map_err(|e| DecodeError::InvalidData(format!("invalid float4: {e}"))),
143 ValueKind::Float8 => OrderedF64::try_from(r.f64()?)
144 .map(Value::Float8)
145 .map_err(|e| DecodeError::InvalidData(format!("invalid float8: {e}"))),
146 ValueKind::Int1 => Ok(Value::Int1(r.i8()?)),
147 ValueKind::Int2 => Ok(Value::Int2(r.i16()?)),
148 ValueKind::Int4 => Ok(Value::Int4(r.i32()?)),
149 ValueKind::Int8 => Ok(Value::Int8(r.i64()?)),
150 ValueKind::Int16 => Ok(Value::Int16(r.i128()?)),
151 ValueKind::Utf8 => Ok(Value::Utf8(decode_len_prefixed_str(r)?.to_string())),
152 ValueKind::Uint1 => Ok(Value::Uint1(r.u8()?)),
153 ValueKind::Uint2 => Ok(Value::Uint2(r.u16()?)),
154 ValueKind::Uint4 => Ok(Value::Uint4(r.u32()?)),
155 ValueKind::Uint8 => Ok(Value::Uint8(r.u64()?)),
156 ValueKind::Uint16 => Ok(Value::Uint16(r.u128()?)),
157 ValueKind::Date => {
158 let days = r.i32()?;
159 Date::from_days_since_epoch(days)
160 .map(Value::Date)
161 .ok_or_else(|| DecodeError::InvalidData(format!("invalid date: {days}")))
162 }
163 ValueKind::DateTime => Ok(Value::DateTime(DateTime::from_nanos(r.u64()?))),
164 ValueKind::Time => {
165 let nanos = r.u64()?;
166 Time::from_nanos_since_midnight(nanos)
167 .map(Value::Time)
168 .ok_or_else(|| DecodeError::InvalidData(format!("invalid time: {nanos}")))
169 }
170 ValueKind::Duration => {
171 let months = r.i32()?;
172 let days = r.i32()?;
173 let nanos = r.i64()?;
174 Duration::new(months, days, nanos)
175 .map(Value::Duration)
176 .map_err(|e| DecodeError::InvalidData(format!("invalid duration: {e}")))
177 }
178 ValueKind::IdentityId => Ok(Value::IdentityId(IdentityId::new(Uuid7(decode_uuid(r)?)))),
179 ValueKind::Uuid4 => Ok(Value::Uuid4(Uuid4(decode_uuid(r)?))),
180 ValueKind::Uuid7 => Ok(Value::Uuid7(Uuid7(decode_uuid(r)?))),
181 ValueKind::Blob => Ok(Value::Blob(Blob::new(decode_len_prefixed_bytes(r)?.to_vec()))),
182 ValueKind::Int => Ok(Value::Int(Int(BigInt::from_signed_bytes_le(decode_len_prefixed_bytes(r)?)))),
183 ValueKind::Uint => Ok(Value::Uint(Uint(BigInt::from_signed_bytes_le(decode_len_prefixed_bytes(r)?)))),
184 ValueKind::Decimal => {
185 let s = decode_len_prefixed_str(r)?;
186 let dec: BigDecimal =
187 s.parse().map_err(|e| DecodeError::InvalidData(format!("invalid decimal: {e}")))?;
188 Ok(Value::Decimal(Decimal::new(dec)))
189 }
190 ValueKind::Any => Ok(Value::Any(Box::new(decode_value_from(r)?))),
191 ValueKind::DictionaryId => {
192 let width = r.u8()?;
193 let id = match width {
194 1 => DictionaryEntryId::U1(r.u8()?),
195 2 => DictionaryEntryId::U2(r.u16()?),
196 4 => DictionaryEntryId::U4(r.u32()?),
197 8 => DictionaryEntryId::U8(r.u64()?),
198 16 => DictionaryEntryId::U16(r.u128()?),
199 other => {
200 return Err(DecodeError::InvalidData(format!(
201 "invalid dictionary id width: {other}"
202 )));
203 }
204 };
205 Ok(Value::DictionaryId(id))
206 }
207 ValueKind::Type => Ok(Value::Type(decode_value_type(r)?)),
208 ValueKind::List => Ok(Value::List(decode_value_sequence(r)?)),
209 ValueKind::Tuple => Ok(Value::Tuple(decode_value_sequence(r)?)),
210 ValueKind::Record => {
211 let count = r.u32()?;
212 let mut fields = Vec::with_capacity((count as usize).min(4096));
213 for _ in 0..count {
214 let key = decode_len_prefixed_str(r)?.to_string();
215 fields.push((key, decode_value_from(r)?));
216 }
217 Ok(Value::Record(fields))
218 }
219 }
220}
221
222fn decode_value_sequence(r: &mut Reader) -> Result<Vec<Value>, DecodeError> {
223 let count = r.u32()?;
224 let mut items = Vec::with_capacity((count as usize).min(4096));
225 for _ in 0..count {
226 items.push(decode_value_from(r)?);
227 }
228 Ok(items)
229}
230
231fn decode_len_prefixed_bytes<'a>(r: &mut Reader<'a>) -> Result<&'a [u8], DecodeError> {
232 let len = r.u32()? as usize;
233 r.take(len)
234}
235
236fn decode_len_prefixed_str<'a>(r: &mut Reader<'a>) -> Result<&'a str, DecodeError> {
237 from_utf8(decode_len_prefixed_bytes(r)?).map_err(|e| DecodeError::InvalidData(format!("invalid UTF-8: {e}")))
238}
239
240fn decode_uuid(r: &mut Reader) -> Result<Uuid, DecodeError> {
241 Ok(Uuid::from_bytes(r.take(16)?.try_into().unwrap()))
242}
243
244pub fn encode_params(params: &Params) -> Result<Vec<u8>, EncodeError> {
245 let mut buf = Vec::new();
246 match params {
247 Params::None => buf.push(0),
248 Params::Positional(values) => {
249 buf.push(1);
250 buf.extend_from_slice(&(values.len() as u32).to_le_bytes());
251 for value in values.iter() {
252 encode_value_into(value, &mut buf)?;
253 }
254 }
255 Params::Named(map) => {
256 buf.push(2);
257 buf.extend_from_slice(&(map.len() as u32).to_le_bytes());
258 for (key, value) in map.iter() {
259 encode_len_prefixed(key.as_bytes(), &mut buf);
260 encode_value_into(value, &mut buf)?;
261 }
262 }
263 }
264 Ok(buf)
265}
266
267pub fn decode_params(bytes: &[u8]) -> Result<Params, DecodeError> {
268 let mut r = Reader::new(bytes);
269 let discriminant = r.u8()?;
270 let params = match discriminant {
271 0 => Params::None,
272 1 => {
273 let count = r.u32()?;
274 let mut values = Vec::with_capacity((count as usize).min(4096));
275 for _ in 0..count {
276 values.push(decode_value_from(&mut r)?);
277 }
278 Params::Positional(values.into())
279 }
280 2 => {
281 let count = r.u32()?;
282 let mut map = HashMap::with_capacity((count as usize).min(4096));
283 for _ in 0..count {
284 let key = decode_len_prefixed_str(&mut r)?.to_string();
285 map.insert(key, decode_value_from(&mut r)?);
286 }
287 Params::Named(map.into())
288 }
289 other => {
290 return Err(DecodeError::InvalidData(format!("invalid params discriminant: {other}")));
291 }
292 };
293 if !r.is_empty() {
294 return Err(DecodeError::TrailingBytes(r.remaining()));
295 }
296 Ok(params)
297}