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