authored_draft_pair.rs (1490B)
1 //! Atomic installation of two opaque authored revisions, without effects. 2 3 use crate::{ 4 Error, 5 authored_draft::{AuthoredDraft, AuthoredDraftRevision}, 6 }; 7 8 /// A fixed pair of distinct drafts belonging to one author. 9 /// 10 /// Both expected heads use the existing single-draft compare-and-swap contract. 11 /// A backend must install both revisions or neither. Only an exact replay of 12 /// both existing revisions succeeds as replay; a partially existing pair is a 13 /// conflict. Historical replay does not establish current head ownership. 14 #[derive(Clone, Debug, Eq, PartialEq)] 15 pub struct AuthoredDraftPair { 16 drafts: [AuthoredDraft; 2], 17 expected_heads: [Option<AuthoredDraftRevision>; 2], 18 } 19 20 impl AuthoredDraftPair { 21 pub fn new( 22 first: AuthoredDraft, 23 first_expected: Option<AuthoredDraftRevision>, 24 second: AuthoredDraft, 25 second_expected: Option<AuthoredDraftRevision>, 26 ) -> Result<Self, Error> { 27 first.validate()?; 28 second.validate()?; 29 if first.draft_id() == second.draft_id() || first.author() != second.author() { 30 return Err(Error::InvalidAuthoredDraft); 31 } 32 Ok(Self { 33 drafts: [first, second], 34 expected_heads: [first_expected, second_expected], 35 }) 36 } 37 38 pub const fn drafts(&self) -> &[AuthoredDraft; 2] { 39 &self.drafts 40 } 41 42 pub const fn expected_heads(&self) -> &[Option<AuthoredDraftRevision>; 2] { 43 &self.expected_heads 44 } 45 }