fraiseql_wire/json/validate/
mod.rs1use crate::protocol::{BackendMessage, FieldDescription};
4use crate::util::oid::is_json_oid;
5use crate::{Result, WireError};
6
7pub fn validate_row_description(msg: &BackendMessage) -> Result<()> {
15 let fields = match msg {
16 BackendMessage::RowDescription(fields) => fields,
17 _ => return Err(WireError::Protocol("expected RowDescription".into())),
18 };
19
20 let field = match fields.as_slice() {
22 [only] => only,
23 _ => {
24 return Err(WireError::InvalidSchema(format!(
25 "expected 1 column, got {}",
26 fields.len()
27 )));
28 }
29 };
30
31 if field.name != "data" {
33 return Err(WireError::InvalidSchema(format!(
34 "expected column named 'data', got '{}'",
35 field.name
36 )));
37 }
38
39 if !is_json_oid(field.type_oid) {
41 return Err(WireError::InvalidSchema(format!(
42 "expected json/jsonb type, got OID {}",
43 field.type_oid
44 )));
45 }
46
47 Ok(())
48}
49
50pub fn extract_field_description(msg: &BackendMessage) -> Result<FieldDescription> {
56 let fields = match msg {
57 BackendMessage::RowDescription(fields) => fields,
58 _ => return Err(WireError::Protocol("expected RowDescription".into())),
59 };
60
61 fields
62 .first()
63 .cloned()
64 .ok_or_else(|| WireError::Protocol("RowDescription has no fields".into()))
65}
66
67#[cfg(test)]
68mod tests;