use core::fmt;
use serde::{Deserialize, Serialize};
use crate::error::Error;
use crate::protocol::ProtocolBehavior;
use crate::put::Put;
use crate::stream::Stream;
#[derive(Serialize, Deserialize, Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct AgentName(u8);
#[derive(Serialize, Deserialize, Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum AgentType {
Server,
Client,
}
impl AgentName {
pub const fn new() -> Self {
const FIRST: AgentName = AgentName(0u8);
FIRST
}
pub const fn next(&self) -> Self {
AgentName(self.0 + 1)
}
pub const fn first() -> Self {
AgentName::new()
}
}
impl Default for AgentName {
fn default() -> Self {
Self::new()
}
}
impl fmt::Display for AgentName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq, Hash)]
pub struct AgentDescriptor {
pub name: AgentName,
pub tls_version: TLSVersion,
pub typ: AgentType,
pub try_reuse: bool,
pub client_authentication: bool,
pub server_authentication: bool,
}
impl Default for AgentDescriptor {
fn default() -> Self {
Self {
name: AgentName::first(),
tls_version: TLSVersion::V1_3,
typ: AgentType::Server,
try_reuse: false,
client_authentication: false,
server_authentication: true,
}
}
}
impl AgentDescriptor {
pub fn new_reusable_server(name: AgentName, tls_version: TLSVersion) -> Self {
Self {
name,
tls_version,
typ: AgentType::Server,
try_reuse: true,
..AgentDescriptor::default()
}
}
pub fn new_reusable_client(name: AgentName, tls_version: TLSVersion) -> Self {
Self {
name,
tls_version,
typ: AgentType::Client,
try_reuse: true,
..AgentDescriptor::default()
}
}
pub fn new_server(name: AgentName, tls_version: TLSVersion) -> Self {
Self {
name,
tls_version,
typ: AgentType::Server,
..AgentDescriptor::default()
}
}
pub fn new_client(name: AgentName, tls_version: TLSVersion) -> Self {
Self {
name,
tls_version,
typ: AgentType::Client,
..AgentDescriptor::default()
}
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq, Hash)]
pub enum TLSVersion {
V1_3,
V1_2,
}
pub struct Agent<PB: ProtocolBehavior> {
descriptor: AgentDescriptor,
put: Box<dyn Put<PB>>,
}
impl<PB: ProtocolBehavior> fmt::Debug for Agent<PB> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Agent")
.field("descriptor", &self.descriptor)
.field("put", &self.put.describe_state())
.finish()
}
}
impl<PB: ProtocolBehavior> PartialEq for Agent<PB> {
fn eq(&self, other: &Self) -> bool {
self.descriptor.name.eq(&other.descriptor.name)
&& self.put.describe_state() == other.put.describe_state()
}
}
impl<PB: ProtocolBehavior> Agent<PB> {
pub fn new(descriptor: AgentDescriptor, put: Box<dyn Put<PB>>) -> Self {
Self { descriptor, put }
}
pub fn progress(&mut self) -> Result<(), Error> {
self.put.progress()
}
pub fn reset(&mut self, new_name: AgentName) -> Result<(), Error> {
self.descriptor.name = new_name;
self.put.reset(new_name)
}
pub fn shutdown(&mut self) -> String {
self.put.shutdown()
}
pub fn is_state_successful(&self) -> bool {
self.put.is_state_successful()
}
pub fn is_reusable_with(&self, other: &AgentDescriptor) -> bool {
self.descriptor.typ == other.typ && self.descriptor.tls_version == other.tls_version
}
pub fn name(&self) -> AgentName {
self.descriptor.name
}
pub fn put(&self) -> &dyn Put<PB> {
self.put.as_ref()
}
pub fn put_mut(&mut self) -> &mut dyn Put<PB> {
self.put.as_mut()
}
}
impl<PB: ProtocolBehavior> Stream<PB> for Agent<PB> {
fn add_to_inbound(&mut self, message_flight: &PB::OpaqueProtocolMessageFlight) {
self.put.add_to_inbound(message_flight)
}
fn take_message_from_outbound(
&mut self,
) -> Result<Option<PB::OpaqueProtocolMessageFlight>, Error> {
self.put.take_message_from_outbound()
}
}