reifydb_sub_server/
response.rs1use reifydb_codec::{
5 frame::{encode::encode_frames, options::EncodeOptions},
6 json::{none_marker, wire_type::to_json as type_to_json},
7};
8use reifydb_value::{
9 reifydb_assertions,
10 value::{Value, diff_type::DiffType, frame::frame::Frame, system_columns::SystemColumn, value_type::ValueType},
11};
12use serde_json::{self, Map, Value as JsonValue, to_string as json_to_string};
13
14pub const CONTENT_TYPE_JSON: &str = "application/vnd.reifydb.json";
15pub const CONTENT_TYPE_FRAMES: &str = "application/vnd.reifydb.frames";
16pub const CONTENT_TYPE_RBCF: &str = "application/vnd.reifydb.rbcf";
17pub const CONTENT_TYPE_PROTO: &str = "application/vnd.reifydb.proto";
18
19pub fn encode_frames_rbcf(frames: &[Frame]) -> Result<Vec<u8>, String> {
20 encode_frames(frames, &EncodeOptions::fast()).map_err(|e| e.to_string())
21}
22
23pub struct ResolvedResponse {
24 pub content_type: String,
25 pub body: String,
26}
27
28pub fn resolve_change_json(frames: Vec<Frame>) -> Result<ResolvedResponse, String> {
29 let envelopes: Vec<JsonValue> = frames.iter().map(change_envelope).collect();
30 Ok(json_response(json_to_string(&envelopes).map_err(|e| e.to_string())?))
31}
32
33fn change_envelope(frame: &Frame) -> JsonValue {
34 let row_count = frame.columns.first().map(|c| c.data.len()).unwrap_or(0);
35 let row_numbers = frame.row_numbers();
36 let rows: Vec<JsonValue> = (0..row_count)
37 .map(|i| {
38 let mut obj = Map::new();
39 if let Some(rn) = row_numbers.get(i) {
40 obj.insert(SystemColumn::RowNumbers.name().to_string(), JsonValue::from(rn.value()));
41 }
42 for col in frame.iter() {
43 obj.insert(col.name.clone(), row_value(&col.data.get_type(), col.data.get_value(i)));
44 }
45 JsonValue::Object(obj)
46 })
47 .collect();
48
49 let mut envelope = Map::new();
50 if let Some(op) = frame.op {
51 envelope.insert("op".to_string(), JsonValue::from(DiffType::as_u8(op)));
52 }
53 envelope.insert("types".to_string(), frame_types(frame));
54 envelope.insert("rows".to_string(), JsonValue::Array(rows));
55 JsonValue::Object(envelope)
56}
57
58pub fn resolve_response_json(frames: Vec<Frame>, unwrap: bool) -> Result<ResolvedResponse, String> {
59 if frames.is_empty() {
60 return Ok(json_response("[]".to_string()));
61 }
62
63 if has_body_column(&frames) {
64 let frame = frames.into_iter().next().unwrap();
65 return Ok(json_response(render_body_column(frame, unwrap)));
66 }
67
68 Ok(json_response(render_frame_rows(&frames, unwrap)))
69}
70
71#[inline]
72fn json_response(body: String) -> ResolvedResponse {
73 ResolvedResponse {
74 content_type: CONTENT_TYPE_JSON.to_string(),
75 body,
76 }
77}
78
79#[inline]
80fn has_body_column(frames: &[Frame]) -> bool {
81 frames.first().map(|f| f.columns.iter().any(|c| c.name == "body")).unwrap_or(false)
82}
83
84#[inline]
85fn render_body_column(frame: Frame, unwrap: bool) -> String {
86 let body_col_idx = frame.columns.iter().position(|c| c.name == "body").unwrap();
87 let body_col = &frame.columns[body_col_idx];
88
89 let row_count = body_col.data.len();
90 if body_col.data.is_utf8() {
91 let values: Vec<String> = (0..row_count).map(|i| body_col.data.as_string(i)).collect();
92 if unwrap || values.len() == 1 {
93 values.into_iter().next().unwrap()
94 } else {
95 format!("[{}]", values.join(", "))
96 }
97 } else {
98 let json_values: Vec<JsonValue> =
99 (0..row_count).map(|i| body_col.data.get_value(i).to_json_value()).collect();
100 reifydb_assertions! {
101 let len = json_values.len();
102 assert!(
103 len > 0,
104 "render_body_column reached the non-utf8 branch with an empty body column, but the \
105 caller already established the frame is non-empty by detecting a body column on it; \
106 indexing json_values[0] would panic on a row_count={len} column"
107 );
108 }
109 if unwrap {
110 json_to_string(&json_values[0]).unwrap()
111 } else {
112 json_to_string(&json_values).unwrap()
113 }
114 }
115}
116
117fn option_depth(ty: &ValueType) -> u32 {
118 let mut depth = 0;
119 let mut base = ty;
120 while let ValueType::Option(inner) = base {
121 depth += 1;
122 base = inner;
123 }
124 depth
125}
126
127fn row_value(column_type: &ValueType, value: Value) -> JsonValue {
128 match &value {
129 Value::None {
130 inner,
131 } => {
132 let wrapped = option_depth(column_type).saturating_sub(option_depth(inner) + 1);
133 if wrapped == 0 {
134 JsonValue::Null
135 } else {
136 JsonValue::String(none_marker(wrapped))
137 }
138 }
139 _ => value.to_json_value(),
140 }
141}
142
143fn frame_types(frame: &Frame) -> JsonValue {
144 let mut types = Map::new();
145 for col in frame.iter() {
146 types.insert(col.name.clone(), type_to_json(&col.data.get_type()));
147 }
148 JsonValue::Object(types)
149}
150
151#[inline]
152fn render_frame_rows(frames: &[Frame], unwrap: bool) -> String {
153 let json_frames = frames_to_json_rows(frames);
154
155 if unwrap && json_frames.len() == 1 && json_frames[0].len() == 1 {
156 return json_to_string(&json_frames[0][0]).unwrap();
157 }
158
159 let envelopes: Vec<JsonValue> = frames
160 .iter()
161 .zip(json_frames)
162 .map(|(frame, rows)| {
163 let mut envelope = Map::new();
164 envelope.insert("types".to_string(), frame_types(frame));
165 envelope.insert("rows".to_string(), JsonValue::Array(rows));
166 JsonValue::Object(envelope)
167 })
168 .collect();
169 json_to_string(&envelopes).unwrap()
170}
171
172fn frames_to_json_rows(frames: &[Frame]) -> Vec<Vec<JsonValue>> {
173 frames.iter()
174 .map(|frame| {
175 let row_count = frame.columns.first().map(|c| c.data.len()).unwrap_or(0);
176 (0..row_count)
177 .map(|i| {
178 let mut obj = Map::new();
179 for col in frame.iter() {
180 obj.insert(
181 col.name.clone(),
182 row_value(&col.data.get_type(), col.data.get_value(i)),
183 );
184 }
185 JsonValue::Object(obj)
186 })
187 .collect()
188 })
189 .collect()
190}