reifydb_sub_server/
response.rs1use reifydb_codec::frame::{encode::encode_frames, options::EncodeOptions};
5use reifydb_value::{
6 reifydb_assertions,
7 value::{diff_type::DiffType, frame::frame::Frame, system_columns::SystemColumn},
8};
9use serde_json::{self, Map, Value as JsonValue, to_string as json_to_string};
10
11pub const CONTENT_TYPE_JSON: &str = "application/vnd.reifydb.json";
12pub const CONTENT_TYPE_FRAMES: &str = "application/vnd.reifydb.frames";
13pub const CONTENT_TYPE_RBCF: &str = "application/vnd.reifydb.rbcf";
14pub const CONTENT_TYPE_PROTO: &str = "application/vnd.reifydb.proto";
15
16pub fn encode_frames_rbcf(frames: &[Frame]) -> Result<Vec<u8>, String> {
17 encode_frames(frames, &EncodeOptions::fast()).map_err(|e| e.to_string())
18}
19
20pub struct ResolvedResponse {
21 pub content_type: String,
22 pub body: String,
23}
24
25pub fn resolve_change_json(frames: Vec<Frame>) -> Result<ResolvedResponse, String> {
26 let envelopes: Vec<JsonValue> = frames.iter().map(change_envelope).collect();
27 Ok(json_response(json_to_string(&envelopes).map_err(|e| e.to_string())?))
28}
29
30fn change_envelope(frame: &Frame) -> JsonValue {
31 let row_count = frame.columns.first().map(|c| c.data.len()).unwrap_or(0);
32 let row_numbers = frame.row_numbers();
33 let rows: Vec<JsonValue> = (0..row_count)
34 .map(|i| {
35 let mut obj = Map::new();
36 if let Some(rn) = row_numbers.get(i) {
37 obj.insert(SystemColumn::RowNumbers.name().to_string(), JsonValue::from(rn.value()));
38 }
39 for col in frame.iter() {
40 obj.insert(col.name.clone(), col.data.get_value(i).to_json_value());
41 }
42 JsonValue::Object(obj)
43 })
44 .collect();
45
46 let mut envelope = Map::new();
47 if let Some(op) = frame.op {
48 envelope.insert("op".to_string(), JsonValue::from(DiffType::as_u8(op)));
49 }
50 envelope.insert("rows".to_string(), JsonValue::Array(rows));
51 JsonValue::Object(envelope)
52}
53
54pub fn resolve_response_json(frames: Vec<Frame>, unwrap: bool) -> Result<ResolvedResponse, String> {
55 if frames.is_empty() {
56 return Ok(json_response("[]".to_string()));
57 }
58
59 if has_body_column(&frames) {
60 let frame = frames.into_iter().next().unwrap();
61 return Ok(json_response(render_body_column(frame, unwrap)));
62 }
63
64 Ok(json_response(render_frame_rows(&frames, unwrap)))
65}
66
67#[inline]
68fn json_response(body: String) -> ResolvedResponse {
69 ResolvedResponse {
70 content_type: CONTENT_TYPE_JSON.to_string(),
71 body,
72 }
73}
74
75#[inline]
76fn has_body_column(frames: &[Frame]) -> bool {
77 frames.first().map(|f| f.columns.iter().any(|c| c.name == "body")).unwrap_or(false)
78}
79
80#[inline]
81fn render_body_column(frame: Frame, unwrap: bool) -> String {
82 let body_col_idx = frame.columns.iter().position(|c| c.name == "body").unwrap();
83 let body_col = &frame.columns[body_col_idx];
84
85 let row_count = body_col.data.len();
86 if body_col.data.is_utf8() {
87 let values: Vec<String> = (0..row_count).map(|i| body_col.data.as_string(i)).collect();
88 if unwrap || values.len() == 1 {
89 values.into_iter().next().unwrap()
90 } else {
91 format!("[{}]", values.join(", "))
92 }
93 } else {
94 let json_values: Vec<JsonValue> =
95 (0..row_count).map(|i| body_col.data.get_value(i).to_json_value()).collect();
96 reifydb_assertions! {
97 let len = json_values.len();
98 assert!(
99 len > 0,
100 "render_body_column reached the non-utf8 branch with an empty body column, but the \
101 caller already established the frame is non-empty by detecting a body column on it; \
102 indexing json_values[0] would panic on a row_count={len} column"
103 );
104 }
105 if unwrap {
106 json_to_string(&json_values[0]).unwrap()
107 } else {
108 json_to_string(&json_values).unwrap()
109 }
110 }
111}
112
113#[inline]
114fn render_frame_rows(frames: &[Frame], unwrap: bool) -> String {
115 let json_frames = frames_to_json_rows(frames);
116
117 if unwrap && json_frames.len() == 1 && json_frames[0].len() == 1 {
118 json_to_string(&json_frames[0][0]).unwrap()
119 } else {
120 json_to_string(&json_frames).unwrap()
121 }
122}
123
124fn frames_to_json_rows(frames: &[Frame]) -> Vec<Vec<JsonValue>> {
125 frames.iter()
126 .map(|frame| {
127 let row_count = frame.columns.first().map(|c| c.data.len()).unwrap_or(0);
128 (0..row_count)
129 .map(|i| {
130 let mut obj = Map::new();
131 for col in frame.iter() {
132 obj.insert(col.name.clone(), col.data.get_value(i).to_json_value());
133 }
134 JsonValue::Object(obj)
135 })
136 .collect()
137 })
138 .collect()
139}