Skip to main content

made_core/value_objects/ceremony/
ceremony_revision.rs

1use serde::{Deserialize, Serialize};
2
3use crate::error::DomainError;
4
5/// How many times a ceremony instance has been committed.
6///
7/// The revision lives in the storage contract rather than in the
8/// aggregate: it protects a write against a concurrent write, not any
9/// invariant of the ceremony itself. Keeping it out of
10/// `CeremonyInstance` also keeps the shape a host has already persisted
11/// from changing underneath it.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
13#[serde(transparent)]
14pub struct CeremonyRevision(u64);
15
16impl CeremonyRevision {
17    /// The revision a ceremony reaches on its first successful commit.
18    pub const INITIAL: Self = Self(1);
19
20    pub fn new(value: u64) -> Result<Self, DomainError> {
21        if value == 0 {
22            return Err(DomainError::MustBeNonZero {
23                field: "ceremony_revision",
24            });
25        }
26        Ok(Self(value))
27    }
28
29    #[must_use]
30    pub fn value(self) -> u64 {
31        self.0
32    }
33
34    #[must_use]
35    pub fn next(self) -> Self {
36        Self(self.0.saturating_add(1))
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn a_stored_ceremony_is_at_least_at_the_initial_revision() {
46        assert_eq!(CeremonyRevision::INITIAL.value(), 1);
47        assert!(CeremonyRevision::new(0).is_err());
48    }
49
50    #[test]
51    fn revisions_advance_by_one() {
52        assert_eq!(CeremonyRevision::INITIAL.next().value(), 2);
53    }
54}