use std::fmt;
use std::hash::Hash;
macro_rules! define_id {
($(#[$meta:meta])* $name:ident) => {
$(#[$meta])*
#[derive(Clone, Eq, PartialEq, Hash, Debug, serde::Serialize, serde::Deserialize)]
#[serde(transparent)]
pub struct $name(String);
impl $name {
pub fn new(s: impl Into<String>) -> Self {
Self(s.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn into_string(self) -> String {
self.0
}
}
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<String> for $name {
fn from(s: String) -> Self {
Self(s)
}
}
impl From<&str> for $name {
fn from(s: &str) -> Self {
Self(s.to_string())
}
}
impl AsRef<str> for $name {
fn as_ref(&self) -> &str {
&self.0
}
}
};
}
define_id!(
RoleId
);
define_id!(
StepId
);
define_id!(
SectionId
);
define_id!(
ActId
);
define_id!(
ParamId
);
define_id!(
MaterialId
);
define_id!(
ArtifactId
);
define_id!(
OutputId
);
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
#[test]
fn ids_are_type_safe() {
let role_id = RoleId::new("witness");
let step_id = StepId::new("witness");
assert_eq!(role_id.as_str(), step_id.as_str());
}
#[test]
fn ids_work_as_hash_keys() {
let mut map: HashMap<RoleId, String> = HashMap::new();
map.insert(RoleId::new("admin"), "Alice".to_string());
map.insert(RoleId::new("witness"), "Bob".to_string());
assert_eq!(map.get(&RoleId::new("admin")), Some(&"Alice".to_string()));
}
#[test]
fn ids_display_nicely() {
let id = RoleId::new("ceremony_admin");
assert_eq!(format!("{id}"), "ceremony_admin");
assert_eq!(format!("{id:?}"), r#"RoleId("ceremony_admin")"#);
}
}