Skip to main content

reifydb_codec/json/
from.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use reifydb_value::{
5	fragment::Fragment,
6	util::{bitvec::BitVec, hex::decode},
7	value::{
8		blob::Blob,
9		container::{
10			blob::BlobContainer, bool::BoolContainer, identity_id::IdentityIdContainer,
11			number::NumberContainer, temporal::TemporalContainer, utf8::Utf8Container, uuid::UuidContainer,
12		},
13		date::Date,
14		datetime::DateTime,
15		decimal::Decimal,
16		diff_type::DiffType,
17		duration::Duration,
18		frame::{column::FrameColumn, data::FrameColumnData, frame::Frame},
19		identity::IdentityId,
20		int::{Int, parse::parse_int},
21		row_number::RowNumber,
22		system_columns::SystemColumns,
23		temporal::parse::{
24			date::parse_date, datetime::parse_datetime, duration::parse_duration, time::parse_time,
25		},
26		time::Time,
27		uint::{Uint, parse::parse_uint},
28		uuid::parse::{parse_uuid4, parse_uuid7},
29		value_type::ValueType,
30	},
31};
32use serde_json::{Error, Value, from_str, from_value};
33
34use crate::json::types::ResponseFrame;
35
36pub fn frames_from_json(json: &str) -> Result<Vec<Frame>, Error> {
37	let response_frames: Vec<ResponseFrame> = from_str(json)?;
38	Ok(response_frames.into_iter().map(response_frame_to_frame).collect())
39}
40
41pub fn convert_envelope_response(body: Value) -> Vec<Frame> {
42	let frames_value = match body {
43		Value::Object(ref map) => map.get("frames"),
44		_ => None,
45	};
46
47	let response_frames: Vec<ResponseFrame> = match frames_value {
48		Some(v) => from_value(v.clone()).unwrap_or_default(),
49		None => return Vec::new(),
50	};
51
52	response_frames.into_iter().map(response_frame_to_frame).collect()
53}
54
55fn response_frame_to_frame(frame: ResponseFrame) -> Frame {
56	let columns = frame
57		.columns
58		.into_iter()
59		.map(|col| FrameColumn {
60			name: col.name,
61			data: convert_column_to_data(col.r#type, col.payload),
62		})
63		.collect();
64
65	let row_numbers = frame.row_numbers.into_iter().map(RowNumber::new).collect();
66	let created_at = frame.created_at.iter().filter_map(|s| parse_datetime(Fragment::internal(s)).ok()).collect();
67	let updated_at = frame.updated_at.iter().filter_map(|s| parse_datetime(Fragment::internal(s)).ok()).collect();
68	let time = frame.time.iter().filter_map(|s| parse_datetime(Fragment::internal(s)).ok()).collect();
69
70	Frame {
71		system: SystemColumns::new(row_numbers, Vec::new(), created_at, updated_at, time),
72		columns,
73		op: frame.op.and_then(DiffType::from_u8),
74	}
75}
76
77pub fn convert_column_to_data(target: ValueType, data: Vec<String>) -> FrameColumnData {
78	match target {
79		ValueType::Option(inner_type) => {
80			let defined: Vec<bool> = data.iter().map(|s| s != "⟪none⟫").collect();
81
82			if defined.iter().all(|&b| !b) {
83				let inner = convert_column_to_data(*inner_type, data);
84				return FrameColumnData::Option {
85					inner: Box::new(inner),
86					bitvec: BitVec::from_slice(&defined),
87				};
88			}
89
90			let bitvec = BitVec::from_slice(&defined);
91			let inner = convert_column_to_data(*inner_type, data);
92
93			if defined.iter().all(|&b| b) {
94				return inner;
95			}
96
97			FrameColumnData::Option {
98				inner: Box::new(inner),
99				bitvec,
100			}
101		}
102		ValueType::Boolean => {
103			let values: Vec<_> = data.into_iter().map(|s| s != "⟪none⟫" && s == "true").collect();
104			FrameColumnData::Bool(BoolContainer::new(values))
105		}
106		ValueType::Float4 => {
107			let values: Vec<_> = data
108				.into_iter()
109				.map(|s| {
110					if s == "⟪none⟫" {
111						0.0f32
112					} else {
113						s.parse::<f32>().unwrap_or(0.0)
114					}
115				})
116				.collect();
117			FrameColumnData::Float4(NumberContainer::new(values))
118		}
119		ValueType::Float8 => {
120			let values: Vec<_> = data
121				.into_iter()
122				.map(|s| {
123					if s == "⟪none⟫" {
124						0.0f64
125					} else {
126						s.parse::<f64>().unwrap_or(0.0)
127					}
128				})
129				.collect();
130			FrameColumnData::Float8(NumberContainer::new(values))
131		}
132		ValueType::Int1 => {
133			let values: Vec<_> = data
134				.into_iter()
135				.map(|s| {
136					if s == "⟪none⟫" {
137						0i8
138					} else {
139						s.parse::<i8>().unwrap_or(0)
140					}
141				})
142				.collect();
143			FrameColumnData::Int1(NumberContainer::new(values))
144		}
145		ValueType::Int2 => {
146			let values: Vec<_> = data
147				.into_iter()
148				.map(|s| {
149					if s == "⟪none⟫" {
150						0i16
151					} else {
152						s.parse::<i16>().unwrap_or(0)
153					}
154				})
155				.collect();
156			FrameColumnData::Int2(NumberContainer::new(values))
157		}
158		ValueType::Int4 => {
159			let values: Vec<_> = data
160				.into_iter()
161				.map(|s| {
162					if s == "⟪none⟫" {
163						0i32
164					} else {
165						s.parse::<i32>().unwrap_or(0)
166					}
167				})
168				.collect();
169			FrameColumnData::Int4(NumberContainer::new(values))
170		}
171		ValueType::Int8 => {
172			let values: Vec<_> = data
173				.into_iter()
174				.map(|s| {
175					if s == "⟪none⟫" {
176						0i64
177					} else {
178						s.parse::<i64>().unwrap_or(0)
179					}
180				})
181				.collect();
182			FrameColumnData::Int8(NumberContainer::new(values))
183		}
184		ValueType::Int16 => {
185			let values: Vec<_> = data
186				.into_iter()
187				.map(|s| {
188					if s == "⟪none⟫" {
189						0i128
190					} else {
191						s.parse::<i128>().unwrap_or(0)
192					}
193				})
194				.collect();
195			FrameColumnData::Int16(NumberContainer::new(values))
196		}
197		ValueType::Uint1 => {
198			let values: Vec<_> = data
199				.into_iter()
200				.map(|s| {
201					if s == "⟪none⟫" {
202						0u8
203					} else {
204						s.parse::<u8>().unwrap_or(0)
205					}
206				})
207				.collect();
208			FrameColumnData::Uint1(NumberContainer::new(values))
209		}
210		ValueType::Uint2 => {
211			let values: Vec<_> = data
212				.into_iter()
213				.map(|s| {
214					if s == "⟪none⟫" {
215						0u16
216					} else {
217						s.parse::<u16>().unwrap_or(0)
218					}
219				})
220				.collect();
221			FrameColumnData::Uint2(NumberContainer::new(values))
222		}
223		ValueType::Uint4 => {
224			let values: Vec<_> = data
225				.into_iter()
226				.map(|s| {
227					if s == "⟪none⟫" {
228						0u32
229					} else {
230						s.parse::<u32>().unwrap_or(0)
231					}
232				})
233				.collect();
234			FrameColumnData::Uint4(NumberContainer::new(values))
235		}
236		ValueType::Uint8 => {
237			let values: Vec<_> = data
238				.into_iter()
239				.map(|s| {
240					if s == "⟪none⟫" {
241						0u64
242					} else {
243						s.parse::<u64>().unwrap_or(0)
244					}
245				})
246				.collect();
247			FrameColumnData::Uint8(NumberContainer::new(values))
248		}
249		ValueType::Uint16 => {
250			let values: Vec<_> = data
251				.into_iter()
252				.map(|s| {
253					if s == "⟪none⟫" {
254						0u128
255					} else {
256						s.parse::<u128>().unwrap_or(0)
257					}
258				})
259				.collect();
260			FrameColumnData::Uint16(NumberContainer::new(values))
261		}
262		ValueType::Utf8 => {
263			let values: Vec<_> = data
264				.into_iter()
265				.map(|s| {
266					if s == "⟪none⟫" {
267						String::new()
268					} else {
269						s
270					}
271				})
272				.collect();
273			FrameColumnData::Utf8(Utf8Container::new(values))
274		}
275		ValueType::Date => {
276			let values: Vec<_> = data
277				.into_iter()
278				.map(|s| {
279					if s == "⟪none⟫" {
280						Date::from_ymd(1970, 1, 1).unwrap()
281					} else {
282						parse_date(Fragment::from(s))
283							.unwrap_or_else(|_| Date::from_ymd(1970, 1, 1).unwrap())
284					}
285				})
286				.collect();
287			FrameColumnData::Date(TemporalContainer::new(values))
288		}
289		ValueType::DateTime => {
290			let values: Vec<_> = data
291				.into_iter()
292				.map(|s| {
293					if s == "⟪none⟫" {
294						DateTime::from_epoch_secs(0).unwrap()
295					} else if let Ok(dt) = parse_datetime(Fragment::testing(&s)) {
296						dt
297					} else if let Ok(timestamp) = s.parse::<i64>() {
298						DateTime::from_epoch_secs(timestamp)
299							.unwrap_or(DateTime::from_epoch_secs(0).unwrap())
300					} else {
301						DateTime::from_epoch_secs(0).unwrap()
302					}
303				})
304				.collect();
305			FrameColumnData::DateTime(TemporalContainer::new(values))
306		}
307		ValueType::Time => {
308			let values: Vec<_> = data
309				.into_iter()
310				.map(|s| {
311					if s == "⟪none⟫" {
312						Time::from_hms(0, 0, 0).unwrap()
313					} else {
314						parse_time(Fragment::from(s))
315							.unwrap_or_else(|_| Time::from_hms(0, 0, 0).unwrap())
316					}
317				})
318				.collect();
319			FrameColumnData::Time(TemporalContainer::new(values))
320		}
321		ValueType::Duration => {
322			let values: Vec<_> = data
323				.into_iter()
324				.map(|s| {
325					if s == "⟪none⟫" {
326						Duration::zero()
327					} else {
328						parse_duration(Fragment::from(s)).unwrap_or_else(|_| Duration::zero())
329					}
330				})
331				.collect();
332			FrameColumnData::Duration(TemporalContainer::new(values))
333		}
334		ValueType::Uuid4 => {
335			let values: Vec<_> = data
336				.into_iter()
337				.map(|s| {
338					if s == "⟪none⟫" {
339						parse_uuid4("00000000-0000-4000-8000-000000000000".into()).unwrap()
340					} else if let Ok(uuid) = parse_uuid4(s.into()) {
341						uuid
342					} else {
343						parse_uuid4("00000000-0000-4000-8000-000000000000".into()).unwrap()
344					}
345				})
346				.collect();
347			FrameColumnData::Uuid4(UuidContainer::new(values))
348		}
349		ValueType::Uuid7 => {
350			let values: Vec<_> = data
351				.into_iter()
352				.map(|s| {
353					if s == "⟪none⟫" {
354						parse_uuid7("00000000-0000-7000-8000-000000000000".into()).unwrap()
355					} else if let Ok(uuid) = parse_uuid7(s.into()) {
356						uuid
357					} else {
358						parse_uuid7("00000000-0000-7000-8000-000000000000".into()).unwrap()
359					}
360				})
361				.collect();
362			FrameColumnData::Uuid7(UuidContainer::new(values))
363		}
364		ValueType::IdentityId => {
365			let values: Vec<_> = data
366				.into_iter()
367				.map(|s| {
368					if s == "⟪none⟫" {
369						IdentityId::from(
370							parse_uuid7("00000000-0000-7000-8000-000000000000".into())
371								.unwrap(),
372						)
373					} else if let Ok(uuid) = parse_uuid7(s.into()) {
374						IdentityId::from(uuid)
375					} else {
376						IdentityId::from(
377							parse_uuid7("00000000-0000-7000-8000-000000000000".into())
378								.unwrap(),
379						)
380					}
381				})
382				.collect();
383			FrameColumnData::IdentityId(IdentityIdContainer::new(values))
384		}
385		ValueType::Blob => {
386			let values: Vec<_> = data
387				.into_iter()
388				.map(|s| {
389					if s == "⟪none⟫" {
390						Blob::new(vec![])
391					} else if let Some(hex_str) = s.strip_prefix("0x") {
392						if let Ok(bytes) = decode(hex_str) {
393							Blob::new(bytes)
394						} else {
395							Blob::new(vec![])
396						}
397					} else {
398						Blob::new(vec![])
399					}
400				})
401				.collect();
402			FrameColumnData::Blob(BlobContainer::new(values))
403		}
404		ValueType::Int => {
405			let values: Vec<_> = data
406				.into_iter()
407				.map(|s| {
408					if s == "⟪none⟫" {
409						Int::zero()
410					} else {
411						parse_int(Fragment::from(s)).unwrap_or_else(|_| Int::zero())
412					}
413				})
414				.collect();
415			FrameColumnData::Int(NumberContainer::new(values))
416		}
417		ValueType::Uint => {
418			let values: Vec<_> = data
419				.into_iter()
420				.map(|s| {
421					if s == "⟪none⟫" {
422						Uint::zero()
423					} else {
424						parse_uint(Fragment::from(s)).unwrap_or_else(|_| Uint::zero())
425					}
426				})
427				.collect();
428			FrameColumnData::Uint(NumberContainer::new(values))
429		}
430		ValueType::Decimal => {
431			let values: Vec<_> = data
432				.into_iter()
433				.map(|s| {
434					if s == "⟪none⟫" {
435						Decimal::zero()
436					} else {
437						s.parse::<Decimal>().unwrap_or_else(|_| Decimal::zero())
438					}
439				})
440				.collect();
441			FrameColumnData::Decimal(NumberContainer::new(values))
442		}
443		ValueType::Any
444		| ValueType::DictionaryId
445		| ValueType::List(_)
446		| ValueType::Record(_)
447		| ValueType::Tuple(_) => {
448			let values: Vec<_> = data
449				.into_iter()
450				.map(|s| {
451					if s == "⟪none⟫" {
452						String::new()
453					} else {
454						s
455					}
456				})
457				.collect();
458			FrameColumnData::Utf8(Utf8Container::new(values))
459		}
460	}
461}