use rc_x509_proto::{
encode,
protocol::v1::{self, DispatchResponse, client_to_server::Message},
};
use tokio_util::bytes::Bytes;
use crate::{
build_version::BuildVersion,
connection::{
GracefulDisconnectionCount, LastConnectedDuration, ReconnectionData,
UngracefulDisconnectionCount,
},
host_runtime::CorrelationId,
};
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
pub enum ClientToServer {
Pong,
ClientHello {
#[cfg_attr(test, proptest(strategy = "crate::tests::arbitrary_bytes()"))]
client_nonce: Bytes,
graceful: GracefulDisconnectionCount,
ungraceful: UngracefulDisconnectionCount,
last_closed_connection_duration_seconds: LastConnectedDuration,
reconnection_data: Option<ReconnectionData>,
version_info: BuildVersion,
app_name: String,
},
DispatchResponse {
correlation_id: CorrelationId,
result: v1::dispatch_response::Result,
},
}
impl From<ClientToServer> for Vec<u8> {
fn from(value: ClientToServer) -> Self {
let wire = match value {
ClientToServer::ClientHello {
client_nonce,
graceful,
ungraceful,
last_closed_connection_duration_seconds: last_conn_duration,
reconnection_data,
version_info,
app_name,
} => Message::ClientHello(v1::ClientHello {
graceful_disconnection_count: graceful.as_raw(),
ungraceful_disconnection_count: ungraceful.as_raw(),
last_closed_connection_duration_seconds: last_conn_duration.as_seconds(),
nonce: client_nonce,
reconnection_data: reconnection_data
.map(|v| v.as_bytes().clone())
.unwrap_or_default(),
version_major: version_info.major(),
version_minor: version_info.minor(),
version_patch: version_info.patch(),
version_commit: version_info.commit().clone(),
app_name,
}),
ClientToServer::Pong => Message::Pong(v1::Pong::default()),
ClientToServer::DispatchResponse {
correlation_id,
result,
} => Message::Dispatch(DispatchResponse {
correlation_id: correlation_id.get(),
result: Some(result),
}),
};
encode(&v1::ClientToServer {
message: Some(wire),
})
}
}
#[cfg(test)]
mod tests {
use proptest::prelude::*;
use super::*;
proptest! {
#[test]
fn prop_message_serialisation(
a in any::<ClientToServer>(),
b in any::<ClientToServer>(),
) {
let a_out = Vec::from(a.clone());
let b_out = Vec::from(b.clone());
assert_eq!(a_out, Vec::from(a.clone()));
assert_eq!(b_out, Vec::from(b.clone()));
assert_eq!(
a == b,
a_out == b_out,
);
}
}
}