use data_encoding::BASE64URL_NOPAD;
use serde::{Serialize, Deserialize};
use strum::EnumDiscriminants;
use crate::peer::{
status,
NodeID
};
use crate::store::{
Op,
Version
};
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Packet {
pub dst: NodeID,
pub src: NodeID,
pub clk: status::Clock,
pub hsh: u64,
pub vec: Vec<status::PeerState>,
pub png: PingOrPong,
pub pyl: Payload
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum PingOrPong {
Ping,
Pong
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum Payload {
Protocol(ProtocolPayload),
Dynamic(DynamicPayload),
None
}
#[derive(
Clone,
Debug,
Serialize,
Deserialize,
PartialEq,
Eq,
EnumDiscriminants
)]
#[strum_discriminants(
name(ProtocolPayloadType),
derive(Serialize, Deserialize)
)]
pub enum ProtocolPayload {
Sync {
counters: Vec<Version>,
ops: Vec<Op>
},
Ops(Vec<Op>),
Quit
}
#[derive(
Clone,
Debug,
Serialize,
Deserialize,
PartialEq,
Eq,
EnumDiscriminants
)]
#[strum_discriminants(
name(DynamicPayloadType),
derive(Serialize, Deserialize)
)]
pub enum DynamicPayload {
Push {
tag: String,
msg: String
},
Query {
tag: String,
msg: String
},
Response {
tag: String,
msg: String,
to: (NodeID, status::Clock)
}
}
impl std::fmt::Debug for Packet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self {src, clk, hsh, dst, vec, png, pyl} = &self;
write!(f, "Packet{{ {src}@{clk}#")?;
BASE64URL_NOPAD.encode_write(&hsh.to_le_bytes(), f)?;
write!(f, " → {dst} | {vec:?} | {png:?} | {pyl:?} }}")
}
}
impl std::ops::Not for PingOrPong {
type Output = Self;
fn not(self) -> Self::Output {
match self {
Self::Ping => Self::Pong,
Self::Pong => Self::Ping
}
}
}
impl Payload {
pub fn or(self, other: Payload) -> Payload {
match self {
Payload::None => other,
_ => self
}
}
}
impl From<ProtocolPayload> for Payload {
fn from(event: ProtocolPayload) -> Self {Self::Protocol(event)}
}
impl From<DynamicPayload> for Payload {
fn from(event: DynamicPayload) -> Self {Self::Dynamic(event)}
}
impl DynamicPayload {
pub fn borrow_tag(&self) -> &String {
match self {
Self::Push{tag, ..} => tag,
Self::Query{tag, ..} => tag,
Self::Response{tag, ..} => tag,
}
}
}