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 { 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 for Vec { 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, }), ] } }