minisql/proto/src/handshake/response.rs
2023-12-31 18:45:50 +01:00

69 lines
2.1 KiB
Rust

use crate::handshake::errors::ClientHandshakeError;
use crate::message::backend::{BackendKeyDataData, BackendMessage, ParameterStatusData};
#[derive(Debug)]
pub struct HandshakeResponse {
pub version: String,
pub process_id: i32,
pub secret_key: i32,
}
impl HandshakeResponse {
pub fn new(name: &str, pid: i32, key: i32) -> Self {
Self {
version: format!("16.0 ({name})"),
process_id: pid,
secret_key: key,
}
}
}
impl TryFrom<&[BackendMessage]> for HandshakeResponse {
type Error = ClientHandshakeError;
fn try_from(messages: &[BackendMessage]) -> Result<Self, Self::Error> {
let mut version = None;
let mut process_id = None;
let mut secret_key = None;
for message in messages {
match message {
BackendMessage::ParameterStatus(data) => {
if data.name.as_str() == "server_version" {
version = Some(String::from(data.value.as_str()));
}
}
BackendMessage::BackendKeyData(data) => {
process_id = Some(data.process);
secret_key = Some(data.secret);
}
// Different messages are ignored during the handshake
_ => {}
}
}
match (version, process_id, secret_key) {
(Some(version), Some(process_id), Some(secret_key)) => Ok(Self {
version,
process_id,
secret_key,
}),
_ => Err(ClientHandshakeError::UnexpectedResponse),
}
}
}
impl From<HandshakeResponse> for Vec<BackendMessage> {
fn from(response: HandshakeResponse) -> Self {
vec![
BackendMessage::ParameterStatus(ParameterStatusData {
name: "server_version".into(),
value: response.version.into(),
}),
BackendMessage::BackendKeyData(BackendKeyDataData {
process: response.process_id,
secret: response.secret_key,
}),
]
}
}