use bytes::{BufMut, BytesMut};
pub fn startup(buf: &mut BytesMut, user: &str, database: &str, params: &[(&str, &str)]) {
let start = buf.len();
buf.put_i32(0); buf.put_i32(196608);
put_cstr(buf, "user");
put_cstr(buf, user);
if !database.is_empty() {
put_cstr(buf, "database");
put_cstr(buf, database);
}
for &(key, value) in params {
put_cstr(buf, key);
put_cstr(buf, value);
}
buf.put_u8(0);
let len = (buf.len() - start) as i32;
buf[start..start + 4].copy_from_slice(&len.to_be_bytes());
}
pub fn ssl_request(buf: &mut BytesMut) {
buf.put_i32(8);
buf.put_i32(80877103);
}
pub fn query(buf: &mut BytesMut, sql: &str) {
encode_message(buf, b'Q', |buf| {
put_cstr(buf, sql);
});
}
pub fn parse(buf: &mut BytesMut, name: &str, sql: &str, param_types: &[u32]) {
encode_message(buf, b'P', |buf| {
put_cstr(buf, name);
put_cstr(buf, sql);
buf.put_i16(param_types.len() as i16);
for &oid in param_types {
buf.put_u32(oid);
}
});
}
pub fn bind(
buf: &mut BytesMut,
portal: &str,
statement: &str,
params: &[Option<&[u8]>],
result_formats: &[i16],
) {
encode_message(buf, b'B', |buf| {
put_cstr(buf, portal);
put_cstr(buf, statement);
buf.put_i16(1); buf.put_i16(1);
buf.put_i16(params.len() as i16);
for param in params {
match param {
Some(data) => {
buf.put_i32(data.len() as i32);
buf.put_slice(data);
}
None => {
buf.put_i32(-1); }
}
}
if result_formats.is_empty() {
buf.put_i16(1); buf.put_i16(1); } else {
buf.put_i16(result_formats.len() as i16);
for &fmt in result_formats {
buf.put_i16(fmt);
}
}
});
}
pub fn describe_statement(buf: &mut BytesMut, name: &str) {
encode_message(buf, b'D', |buf| {
buf.put_u8(b'S');
put_cstr(buf, name);
});
}
pub fn describe_portal(buf: &mut BytesMut, name: &str) {
encode_message(buf, b'D', |buf| {
buf.put_u8(b'P');
put_cstr(buf, name);
});
}
pub fn execute(buf: &mut BytesMut, portal: &str, max_rows: i32) {
encode_message(buf, b'E', |buf| {
put_cstr(buf, portal);
buf.put_i32(max_rows); });
}
pub fn sync(buf: &mut BytesMut) {
encode_message(buf, b'S', |_| {});
}
pub fn flush(buf: &mut BytesMut) {
encode_message(buf, b'H', |_| {});
}
pub fn close_statement(buf: &mut BytesMut, name: &str) {
encode_message(buf, b'C', |buf| {
buf.put_u8(b'S');
put_cstr(buf, name);
});
}
pub fn close_portal(buf: &mut BytesMut, name: &str) {
encode_message(buf, b'C', |buf| {
buf.put_u8(b'P');
put_cstr(buf, name);
});
}
pub fn terminate(buf: &mut BytesMut) {
encode_message(buf, b'X', |_| {});
}
pub fn copy_data(buf: &mut BytesMut, data: &[u8]) {
encode_message(buf, b'd', |buf| {
buf.put_slice(data);
});
}
pub fn copy_done(buf: &mut BytesMut) {
encode_message(buf, b'c', |_| {});
}
pub fn copy_fail(buf: &mut BytesMut, message: &str) {
encode_message(buf, b'f', |buf| {
put_cstr(buf, message);
});
}
pub fn password(buf: &mut BytesMut, password: &str) {
encode_message(buf, b'p', |buf| {
put_cstr(buf, password);
});
}
pub fn sasl_initial_response(buf: &mut BytesMut, mechanism: &str, data: &[u8]) {
encode_message(buf, b'p', |buf| {
put_cstr(buf, mechanism);
buf.put_i32(data.len() as i32);
buf.put_slice(data);
});
}
pub fn sasl_response(buf: &mut BytesMut, data: &[u8]) {
encode_message(buf, b'p', |buf| {
buf.put_slice(data);
});
}
pub fn cancel_request(buf: &mut BytesMut, process_id: i32, secret_key: i32) {
buf.put_i32(16); buf.put_i32(80877102); buf.put_i32(process_id);
buf.put_i32(secret_key);
}
fn encode_message(buf: &mut BytesMut, msg_type: u8, encode_body: impl FnOnce(&mut BytesMut)) {
buf.put_u8(msg_type);
let len_idx = buf.len();
buf.put_i32(0); encode_body(buf);
let len = (buf.len() - len_idx) as i32;
buf[len_idx..len_idx + 4].copy_from_slice(&len.to_be_bytes());
}
fn put_cstr(buf: &mut BytesMut, s: &str) {
buf.put_slice(s.as_bytes());
buf.put_u8(0);
}