firebird_wire/wire/
response.rs1use crate::error::{DatabaseError, Error, Result, StatusArg, StatusVector};
4use crate::wire::consts::{arg, op};
5use crate::wire::stream::{FbStream, op_name};
6
7#[derive(Debug, Clone)]
9pub struct Response {
10 pub handle: i32,
12 pub blob_id: u64,
14 pub data: Vec<u8>,
16 pub status: StatusVector,
18}
19
20impl Response {
21 pub fn into_result(self) -> Result<Response> {
24 if self.status.is_error() {
25 return Err(Error::Database(DatabaseError::new(self.status)));
26 }
27 Ok(self)
28 }
29}
30
31pub fn read_op(stream: &mut FbStream) -> Result<i32> {
34 loop {
35 let code = stream.read_i32()?;
36 if code == op::DUMMY || code == op::VOID {
37 continue;
38 }
39 return Ok(code);
40 }
41}
42
43pub fn read_status_vector(stream: &mut FbStream) -> Result<StatusVector> {
45 let mut args = Vec::new();
46 let mut sql_state = None;
47
48 loop {
49 let tag = stream.read_i32()?;
50 match tag {
51 t if t == arg::END => break,
52 t if t == arg::GDS => args.push(StatusArg::Gds(stream.read_i32()?)),
53 t if t == arg::WARNING => args.push(StatusArg::Warning(stream.read_i32()?)),
54 t if t == arg::NUMBER => args.push(StatusArg::Number(stream.read_i32()?)),
55 t if t == arg::STRING || t == arg::CSTRING => {
56 let s = String::from_utf8_lossy(&stream.read_bytes()?).into_owned();
57 args.push(StatusArg::Str(s));
58 }
59 t if t == arg::INTERPRETED => {
60 let s = String::from_utf8_lossy(&stream.read_bytes()?).into_owned();
61 args.push(StatusArg::Interpreted(s));
62 }
63 t if t == arg::SQL_STATE => {
64 sql_state = Some(String::from_utf8_lossy(&stream.read_bytes()?).into_owned());
65 }
66 other => {
67 let _ = stream.read_i32()?;
68 args.push(StatusArg::Number(other));
69 }
70 }
71 }
72
73 Ok(StatusVector { args, sql_state })
74}
75
76pub fn read_response_body(stream: &mut FbStream) -> Result<Response> {
78 let handle = stream.read_i32()?;
79 let blob_id = stream.read_quad()?;
80 let data = stream.read_bytes()?;
81 let status = read_status_vector(stream)?;
82 Ok(Response {
83 handle,
84 blob_id,
85 data,
86 status,
87 })
88}
89
90pub fn read_response(stream: &mut FbStream) -> Result<Response> {
93 let code = read_op(stream)?;
94 if code != op::RESPONSE {
95 stream.mark_broken();
98 return Err(Error::protocol(format!(
99 "expected op_response, got {} ({code})",
100 op_name(code)
101 )));
102 }
103 read_response_body(stream)?.into_result()
104}