Skip to main content

made_core/value_objects/ceremony/
expected_revision.rs

1use serde::{Deserialize, Serialize};
2
3use super::CeremonyRevision;
4
5/// What the caller believes is stored, checked before a commit lands.
6///
7/// Creating and updating are distinguished on purpose: without
8/// [`ExpectedRevision::New`], two callers could both believe they are
9/// starting a ceremony and the second would silently overwrite the
10/// first.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
12#[serde(rename_all = "snake_case", tag = "expected")]
13pub enum ExpectedRevision {
14    /// Nothing is stored for this ceremony yet.
15    New,
16    /// Exactly this revision is stored.
17    Exactly(CeremonyRevision),
18}
19
20impl ExpectedRevision {
21    #[must_use]
22    pub fn matches(self, stored: Option<CeremonyRevision>) -> bool {
23        match (self, stored) {
24            (Self::New, None) => true,
25            (Self::Exactly(expected), Some(stored)) => expected == stored,
26            _ => false,
27        }
28    }
29
30    /// The revision a commit produces when this expectation holds.
31    #[must_use]
32    pub fn resulting_revision(self) -> CeremonyRevision {
33        match self {
34            Self::New => CeremonyRevision::INITIAL,
35            Self::Exactly(stored) => stored.next(),
36        }
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn new_matches_only_an_absent_ceremony() {
46        assert!(ExpectedRevision::New.matches(None));
47        assert!(!ExpectedRevision::New.matches(Some(CeremonyRevision::INITIAL)));
48    }
49
50    #[test]
51    fn exactly_matches_only_that_revision() {
52        let expectation = ExpectedRevision::Exactly(CeremonyRevision::INITIAL);
53
54        assert!(expectation.matches(Some(CeremonyRevision::INITIAL)));
55        assert!(!expectation.matches(Some(CeremonyRevision::INITIAL.next())));
56        assert!(!expectation.matches(None));
57    }
58
59    #[test]
60    fn a_first_commit_produces_the_initial_revision() {
61        assert_eq!(
62            ExpectedRevision::New.resulting_revision(),
63            CeremonyRevision::INITIAL
64        );
65        assert_eq!(
66            ExpectedRevision::Exactly(CeremonyRevision::INITIAL).resulting_revision(),
67            CeremonyRevision::INITIAL.next()
68        );
69    }
70}