use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Ceremony {
pub enactment: String,
pub step: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub definition: Option<String>,
#[serde(
rename = "definitionDigest",
default,
skip_serializing_if = "Option::is_none"
)]
pub definition_digest: Option<String>,
#[serde(
rename = "parentEnactment",
default,
skip_serializing_if = "Option::is_none"
)]
pub parent_enactment: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub round: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub terminal: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub prev: Option<Vec<CeremonyPrev>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CeremonyPrev {
pub id: String,
#[serde(rename = "digestMultibase")]
pub digest_multibase: String,
}
impl Ceremony {
pub fn new(enactment: impl Into<String>, step: impl Into<String>) -> Self {
Self {
enactment: enactment.into(),
step: step.into(),
definition: None,
definition_digest: None,
parent_enactment: None,
round: None,
terminal: None,
prev: None,
}
}
pub fn is_well_formed(&self) -> bool {
if self.definition.is_some() != self.definition_digest.is_some() {
return false;
}
if self.parent_enactment.as_deref() == Some(self.enactment.as_str()) {
return false;
}
true
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn definition_requires_a_digest() {
let mut c = Ceremony::new("urn:uuid:e", "apply");
assert!(c.is_well_formed());
c.definition = Some("https://trusttasks.org/ceremony/x/0.1".into());
assert!(
!c.is_well_formed(),
"definition without digest is malformed"
);
c.definition_digest = Some("zQmExample".into());
assert!(c.is_well_formed());
}
#[test]
fn an_enactment_cannot_contain_itself() {
let mut c = Ceremony::new("urn:uuid:e", "apply");
c.parent_enactment = Some("urn:uuid:e".into());
assert!(!c.is_well_formed());
c.parent_enactment = Some("urn:uuid:outer".into());
assert!(c.is_well_formed());
}
#[test]
fn optional_members_are_omitted_not_nulled() {
let json = serde_json::to_string(&Ceremony::new("urn:uuid:e", "apply")).unwrap();
assert_eq!(json, r#"{"enactment":"urn:uuid:e","step":"apply"}"#);
}
}