sentinel_driver/protocol/
frontend.rs1use bytes::{BufMut, BytesMut};
2
3pub fn startup(buf: &mut BytesMut, user: &str, database: &str, params: &[(&str, &str)]) {
7 let start = buf.len();
8 buf.put_i32(0); buf.put_i32(196608); put_cstr(buf, "user");
12 put_cstr(buf, user);
13
14 if !database.is_empty() {
15 put_cstr(buf, "database");
16 put_cstr(buf, database);
17 }
18
19 for &(key, value) in params {
20 put_cstr(buf, key);
21 put_cstr(buf, value);
22 }
23
24 buf.put_u8(0); let len = (buf.len() - start) as i32;
27 buf[start..start + 4].copy_from_slice(&len.to_be_bytes());
28}
29
30pub fn ssl_request(buf: &mut BytesMut) {
34 buf.put_i32(8);
35 buf.put_i32(80877103);
36}
37
38pub fn query(buf: &mut BytesMut, sql: &str) {
40 encode_message(buf, b'Q', |buf| {
41 put_cstr(buf, sql);
42 });
43}
44
45pub fn parse(buf: &mut BytesMut, name: &str, sql: &str, param_types: &[u32]) {
47 encode_message(buf, b'P', |buf| {
48 put_cstr(buf, name);
49 put_cstr(buf, sql);
50 buf.put_i16(param_types.len() as i16);
51 for &oid in param_types {
52 buf.put_u32(oid);
53 }
54 });
55}
56
57pub fn bind(
61 buf: &mut BytesMut,
62 portal: &str,
63 statement: &str,
64 params: &[Option<&[u8]>],
65 result_formats: &[i16],
66) {
67 encode_message(buf, b'B', |buf| {
68 put_cstr(buf, portal);
69 put_cstr(buf, statement);
70
71 buf.put_i16(1); buf.put_i16(1); buf.put_i16(params.len() as i16);
77 for param in params {
78 match param {
79 Some(data) => {
80 buf.put_i32(data.len() as i32);
81 buf.put_slice(data);
82 }
83 None => {
84 buf.put_i32(-1); }
86 }
87 }
88
89 if result_formats.is_empty() {
91 buf.put_i16(1); buf.put_i16(1); } else {
94 buf.put_i16(result_formats.len() as i16);
95 for &fmt in result_formats {
96 buf.put_i16(fmt);
97 }
98 }
99 });
100}
101
102pub fn describe_statement(buf: &mut BytesMut, name: &str) {
104 encode_message(buf, b'D', |buf| {
105 buf.put_u8(b'S');
106 put_cstr(buf, name);
107 });
108}
109
110pub fn describe_portal(buf: &mut BytesMut, name: &str) {
112 encode_message(buf, b'D', |buf| {
113 buf.put_u8(b'P');
114 put_cstr(buf, name);
115 });
116}
117
118pub fn execute(buf: &mut BytesMut, portal: &str, max_rows: i32) {
120 encode_message(buf, b'E', |buf| {
121 put_cstr(buf, portal);
122 buf.put_i32(max_rows); });
124}
125
126pub fn sync(buf: &mut BytesMut) {
128 encode_message(buf, b'S', |_| {});
129}
130
131pub fn flush(buf: &mut BytesMut) {
133 encode_message(buf, b'H', |_| {});
134}
135
136pub fn close_statement(buf: &mut BytesMut, name: &str) {
138 encode_message(buf, b'C', |buf| {
139 buf.put_u8(b'S');
140 put_cstr(buf, name);
141 });
142}
143
144pub fn close_portal(buf: &mut BytesMut, name: &str) {
146 encode_message(buf, b'C', |buf| {
147 buf.put_u8(b'P');
148 put_cstr(buf, name);
149 });
150}
151
152pub fn terminate(buf: &mut BytesMut) {
154 encode_message(buf, b'X', |_| {});
155}
156
157pub fn copy_data(buf: &mut BytesMut, data: &[u8]) {
159 encode_message(buf, b'd', |buf| {
160 buf.put_slice(data);
161 });
162}
163
164pub fn copy_done(buf: &mut BytesMut) {
166 encode_message(buf, b'c', |_| {});
167}
168
169pub fn copy_fail(buf: &mut BytesMut, message: &str) {
171 encode_message(buf, b'f', |buf| {
172 put_cstr(buf, message);
173 });
174}
175
176pub fn password(buf: &mut BytesMut, password: &str) {
178 encode_message(buf, b'p', |buf| {
179 put_cstr(buf, password);
180 });
181}
182
183pub fn sasl_initial_response(buf: &mut BytesMut, mechanism: &str, data: &[u8]) {
185 encode_message(buf, b'p', |buf| {
186 put_cstr(buf, mechanism);
187 buf.put_i32(data.len() as i32);
188 buf.put_slice(data);
189 });
190}
191
192pub fn sasl_response(buf: &mut BytesMut, data: &[u8]) {
194 encode_message(buf, b'p', |buf| {
195 buf.put_slice(data);
196 });
197}
198
199pub fn cancel_request(buf: &mut BytesMut, process_id: i32, secret_key: i32) {
206 buf.put_i32(16); buf.put_i32(80877102); buf.put_i32(process_id);
209 buf.put_i32(secret_key);
210}
211
212fn encode_message(buf: &mut BytesMut, msg_type: u8, encode_body: impl FnOnce(&mut BytesMut)) {
216 buf.put_u8(msg_type);
217 let len_idx = buf.len();
218 buf.put_i32(0); encode_body(buf);
220 let len = (buf.len() - len_idx) as i32;
221 buf[len_idx..len_idx + 4].copy_from_slice(&len.to_be_bytes());
222}
223
224fn put_cstr(buf: &mut BytesMut, s: &str) {
226 buf.put_slice(s.as_bytes());
227 buf.put_u8(0);
228}