use core::{any::type_name, fmt::Display};
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct Interaction {
hierarchy: Hierarchy,
kind: Kind,
label: Label,
type_name: &'static str,
length: Length,
}
pub type Label = &'static str;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum Kind {
Protocol,
Public,
Message,
Hint,
Challenge,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum Hierarchy {
Atomic,
Begin,
End,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum Length {
None,
Scalar,
Fixed(usize),
Dynamic,
}
impl Interaction {
#[must_use]
pub fn new<T: ?Sized>(hierarchy: Hierarchy, kind: Kind, label: Label, length: Length) -> Self {
let type_name = type_name::<T>();
Self {
hierarchy,
kind,
label,
type_name,
length,
}
}
#[must_use]
pub const fn hierarchy(&self) -> Hierarchy {
self.hierarchy
}
#[must_use]
pub const fn kind(&self) -> Kind {
self.kind
}
#[must_use]
pub(super) fn closes(&self, other: &Self) -> bool {
self.hierarchy == Hierarchy::End
&& other.hierarchy == Hierarchy::Begin
&& self.kind == other.kind
&& self.label == other.label
&& self.type_name == other.type_name
&& self.length == other.length
}
}
impl Display for Interaction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if f.alternate() {
write!(f, "{} {}", self.hierarchy, self.kind)?;
write!(f, " {} {}", self.label.len(), self.label)?;
write!(f, " {}", self.length)
} else {
write!(
f,
"{} {} {} {} {}",
self.hierarchy, self.kind, self.label, self.length, self.type_name,
)
}
}
}
impl Display for Hierarchy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Atomic => write!(f, "Atomic"),
Self::Begin => write!(f, "Begin"),
Self::End => write!(f, "End"),
}
}
}
impl Display for Kind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Protocol => write!(f, "Protocol"),
Self::Public => write!(f, "Public"),
Self::Message => write!(f, "Message"),
Self::Hint => write!(f, "Hint"),
Self::Challenge => write!(f, "Challenge"),
}
}
}
impl Display for Length {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::None => write!(f, "None"),
Self::Scalar => write!(f, "Scalar"),
Self::Fixed(size) => write!(f, "Fixed({size})"),
Self::Dynamic => write!(f, "Dynamic"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_domain_separator() {
let interaction = Interaction::new::<Vec<f64>>(
Hierarchy::Atomic,
Kind::Message,
"test-message",
Length::Scalar,
);
let result = format!("{interaction:#}");
let expected = "Atomic Message 12 test-message Scalar";
assert_eq!(result, expected);
}
}