use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum ActorKind {
Human,
Agent,
Service,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ActorId {
pub kind: ActorKind,
pub name: String,
}
impl ActorId {
pub fn human(name: impl Into<String>) -> Self {
Self {
kind: ActorKind::Human,
name: name.into(),
}
}
pub fn agent(name: impl Into<String>) -> Self {
Self {
kind: ActorKind::Agent,
name: name.into(),
}
}
pub fn service(name: impl Into<String>) -> Self {
Self {
kind: ActorKind::Service,
name: name.into(),
}
}
}
impl std::fmt::Display for ActorKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Self::Human => "human",
Self::Agent => "agent",
Self::Service => "service",
})
}
}
impl std::fmt::Display for ActorId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", self.kind, self.name)
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum ActorParseError {
#[error("actor {0:?} must be human:NAME, agent:NAME, or service:NAME")]
MissingKind(String),
#[error("unknown actor kind {0}")]
UnknownKind(String),
#[error("actor name must not be empty")]
EmptyName,
}
impl std::str::FromStr for ActorId {
type Err = ActorParseError;
fn from_str(value: &str) -> Result<Self, Self::Err> {
let (kind, name) = value
.split_once(':')
.ok_or_else(|| ActorParseError::MissingKind(value.into()))?;
if name.trim().is_empty() {
return Err(ActorParseError::EmptyName);
}
let kind = match kind {
"human" => ActorKind::Human,
"agent" => ActorKind::Agent,
"service" => ActorKind::Service,
_ => return Err(ActorParseError::UnknownKind(kind.into())),
};
Ok(Self {
kind,
name: name.into(),
})
}
}