1use reifydb_value::{
5 util::hex::encode,
6 value::{Value, column_view::ColumnView, diff_type::DiffType, frame::frame::Frame, value_type::ValueType},
7};
8use serde::ser::Error as _;
9use serde_json::{Error, Value as JsonValue, to_string};
10
11use crate::{
12 json::{
13 none_marker,
14 types::{ResponseColumn, ResponseFrame},
15 wire_type::WireValueType,
16 },
17 tag::peel_options,
18};
19
20pub fn value_to_json(value: &Value, declared: &ValueType) -> JsonValue {
21 let depth = peel_options(declared).1;
22 match value {
23 Value::None {
24 inner,
25 } => JsonValue::String(none_marker(depth.saturating_sub(peel_options(inner).1 + 1))),
26 Value::Blob(b) => JsonValue::String(b.to_hex()),
27 Value::Digest(digest) => JsonValue::String(format!("0x{}", encode(&digest.encode()))),
28 Value::List(items) => {
29 let elem_ty = match peel_options(declared).0 {
30 ValueType::List(inner) => inner.as_ref(),
31 _ => &ValueType::Any,
32 };
33 JsonValue::Array(items.iter().map(|item| value_to_json(item, elem_ty)).collect())
34 }
35 Value::Record(fields) => {
36 let field_types: &[(String, ValueType)] = match peel_options(declared).0 {
37 ValueType::Record(f) => f.as_slice(),
38 _ => &[],
39 };
40 JsonValue::Object(
41 fields.iter()
42 .map(|(name, item)| {
43 let field_ty = field_types
44 .iter()
45 .find(|(n, _)| n == name)
46 .map(|(_, t)| t)
47 .unwrap_or(&ValueType::Any);
48 (name.clone(), value_to_json(item, field_ty))
49 })
50 .collect(),
51 )
52 }
53 _ => JsonValue::String(value.to_string()),
54 }
55}
56
57pub fn convert_frames(frames: &[Frame]) -> Result<Vec<ResponseFrame>, Error> {
58 let mut result = Vec::new();
59
60 for frame in frames {
61 let mut columns = Vec::new();
62
63 let schema = frame.batch.schema_ref();
64 for (field, array) in schema.fields().iter().zip(frame.batch.columns()) {
65 let view = ColumnView::try_from((array, field.as_ref())).map_err(Error::custom)?;
66 let column_type = view.get_type();
67 let column_data: Vec<JsonValue> =
68 view.iter().map(|value| value_to_json(&value, &column_type)).collect();
69
70 columns.push(ResponseColumn {
71 name: field.name().clone(),
72 r#type: WireValueType(column_type),
73 payload: column_data,
74 });
75 }
76
77 result.push(ResponseFrame {
78 op: frame.op.map(DiffType::as_u8),
79 row_numbers: Vec::new(),
80 created_at: Vec::new(),
81 updated_at: Vec::new(),
82 time: Vec::new(),
83 columns,
84 });
85 }
86
87 Ok(result)
88}
89
90pub fn frames_to_json(frames: &[Frame]) -> Result<String, Error> {
91 let response_frames = convert_frames(frames)?;
92 to_string(&response_frames)
93}