1use crate::Label;
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
13pub enum Action {
14 Send,
16 Recv,
18}
19
20impl Action {
21 #[must_use]
23 pub fn dual(&self) -> Self {
24 match self {
25 Action::Send => Action::Recv,
26 Action::Recv => Action::Send,
27 }
28 }
29
30 #[must_use]
32 pub fn is_send(&self) -> bool {
33 matches!(self, Action::Send)
34 }
35
36 #[must_use]
38 pub fn is_recv(&self) -> bool {
39 matches!(self, Action::Recv)
40 }
41}
42
43impl std::fmt::Display for Action {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 match self {
46 Action::Send => write!(f, "!"),
47 Action::Recv => write!(f, "?"),
48 }
49 }
50}
51
52#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
68pub struct LocalAction {
69 action: Action,
71 partner: String,
73 label: Label,
75}
76
77impl LocalAction {
78 #[must_use]
80 pub fn new(action: Action, partner: impl Into<String>, label: Label) -> Self {
81 Self {
82 action,
83 partner: partner.into(),
84 label,
85 }
86 }
87
88 #[must_use]
90 pub fn send(partner: impl Into<String>, label: Label) -> Self {
91 Self::new(Action::Send, partner, label)
92 }
93
94 #[must_use]
96 pub fn recv(partner: impl Into<String>, label: Label) -> Self {
97 Self::new(Action::Recv, partner, label)
98 }
99
100 #[must_use]
102 pub fn action(&self) -> Action {
103 self.action
104 }
105
106 #[must_use]
108 pub fn partner(&self) -> &str {
109 &self.partner
110 }
111
112 #[must_use]
114 pub fn label(&self) -> &Label {
115 &self.label
116 }
117
118 #[must_use]
120 pub fn is_send(&self) -> bool {
121 self.action.is_send()
122 }
123
124 #[must_use]
126 pub fn is_recv(&self) -> bool {
127 self.action.is_recv()
128 }
129
130 #[must_use]
132 pub fn dual(&self) -> Self {
133 Self {
134 action: self.action.dual(),
135 partner: self.partner.clone(),
136 label: self.label.clone(),
137 }
138 }
139}
140
141impl std::fmt::Display for LocalAction {
142 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143 write!(f, "{}{}{{{}}}", self.action, self.partner, self.label)
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150
151 #[test]
152 fn test_action_dual() {
153 assert_eq!(Action::Send.dual(), Action::Recv);
154 assert_eq!(Action::Recv.dual(), Action::Send);
155 }
156
157 #[test]
158 fn test_action_display() {
159 assert_eq!(format!("{}", Action::Send), "!");
160 assert_eq!(format!("{}", Action::Recv), "?");
161 }
162
163 #[test]
164 fn test_local_action_new() {
165 let action = LocalAction::new(Action::Send, "B", Label::new("msg"));
166 assert!(action.is_send());
167 assert_eq!(action.partner(), "B");
168 assert_eq!(action.label().name, "msg");
169 }
170
171 #[test]
172 fn test_local_action_send_recv() {
173 let send = LocalAction::send("B", Label::new("hello"));
174 let recv = LocalAction::recv("A", Label::new("world"));
175
176 assert!(send.is_send());
177 assert!(!send.is_recv());
178 assert!(recv.is_recv());
179 assert!(!recv.is_send());
180 }
181
182 #[test]
183 fn test_local_action_dual() {
184 let send = LocalAction::send("B", Label::new("msg"));
185 let recv = send.dual();
186
187 assert!(recv.is_recv());
188 assert_eq!(recv.partner(), "B");
189 assert_eq!(recv.label().name, "msg");
190 }
191
192 #[test]
193 fn test_local_action_display() {
194 let action = LocalAction::send("B", Label::new("hello"));
195 assert_eq!(format!("{}", action), "!B{hello}");
196
197 let recv = LocalAction::recv("A", Label::new("data"));
198 assert_eq!(format!("{}", recv), "?A{data}");
199 }
200}