use crate::Label;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Action {
Send,
Recv,
}
impl Action {
#[must_use]
pub fn dual(&self) -> Self {
match self {
Action::Send => Action::Recv,
Action::Recv => Action::Send,
}
}
#[must_use]
pub fn is_send(&self) -> bool {
matches!(self, Action::Send)
}
#[must_use]
pub fn is_recv(&self) -> bool {
matches!(self, Action::Recv)
}
}
impl std::fmt::Display for Action {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Action::Send => write!(f, "!"),
Action::Recv => write!(f, "?"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct LocalAction {
action: Action,
partner: String,
label: Label,
}
impl LocalAction {
#[must_use]
pub fn new(action: Action, partner: impl Into<String>, label: Label) -> Self {
Self {
action,
partner: partner.into(),
label,
}
}
#[must_use]
pub fn send(partner: impl Into<String>, label: Label) -> Self {
Self::new(Action::Send, partner, label)
}
#[must_use]
pub fn recv(partner: impl Into<String>, label: Label) -> Self {
Self::new(Action::Recv, partner, label)
}
#[must_use]
pub fn action(&self) -> Action {
self.action
}
#[must_use]
pub fn partner(&self) -> &str {
&self.partner
}
#[must_use]
pub fn label(&self) -> &Label {
&self.label
}
#[must_use]
pub fn is_send(&self) -> bool {
self.action.is_send()
}
#[must_use]
pub fn is_recv(&self) -> bool {
self.action.is_recv()
}
#[must_use]
pub fn dual(&self) -> Self {
Self {
action: self.action.dual(),
partner: self.partner.clone(),
label: self.label.clone(),
}
}
}
impl std::fmt::Display for LocalAction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}{}{{{}}}", self.action, self.partner, self.label)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_action_dual() {
assert_eq!(Action::Send.dual(), Action::Recv);
assert_eq!(Action::Recv.dual(), Action::Send);
}
#[test]
fn test_action_display() {
assert_eq!(format!("{}", Action::Send), "!");
assert_eq!(format!("{}", Action::Recv), "?");
}
#[test]
fn test_local_action_new() {
let action = LocalAction::new(Action::Send, "B", Label::new("msg"));
assert!(action.is_send());
assert_eq!(action.partner(), "B");
assert_eq!(action.label().name, "msg");
}
#[test]
fn test_local_action_send_recv() {
let send = LocalAction::send("B", Label::new("hello"));
let recv = LocalAction::recv("A", Label::new("world"));
assert!(send.is_send());
assert!(!send.is_recv());
assert!(recv.is_recv());
assert!(!recv.is_send());
}
#[test]
fn test_local_action_dual() {
let send = LocalAction::send("B", Label::new("msg"));
let recv = send.dual();
assert!(recv.is_recv());
assert_eq!(recv.partner(), "B");
assert_eq!(recv.label().name, "msg");
}
#[test]
fn test_local_action_display() {
let action = LocalAction::send("B", Label::new("hello"));
assert_eq!(format!("{}", action), "!B{hello}");
let recv = LocalAction::recv("A", Label::new("data"));
assert_eq!(format!("{}", recv), "?A{data}");
}
}