Skip to main content

coven_sync/
operation_outcome.rs

1//! Reading how an operation ended (ยง11.4, api.md E6): the kinds
2//! `coven_operations` lists, and an outcome as a waiting call's result.
3
4use crate::{OperationKind, OperationOutcome, SyncError};
5use coven_database::types::{FromSql, FromSqlError, FromSqlResult, ValueRef};
6use coven_merge::Slot;
7
8/// The landed slot, or the rejection as the error of a call that waits for
9/// the operation itself.
10pub(crate) fn into_slot(outcome: OperationOutcome) -> Result<Option<Slot>, SyncError> {
11    match outcome {
12        OperationOutcome::Landed(slot) => Ok(Some(slot)),
13        OperationOutcome::Satisfied => Ok(None),
14        OperationOutcome::Rejected(reason) => Err(SyncError::Rejected(reason)),
15        // Only an operation the app's write journaled ends stopped, and no
16        // call waits for one: its outcome is the app's to read.
17        OperationOutcome::Stopped(_) => Err(coven_database::DbError::Invariant {
18            what: "a call waits only for operations a stop doesn't end",
19        }
20        .into()),
21        // Only storage setup ends cancelled or undone, and it waits for no
22        // sequence operation's outcome this way.
23        OperationOutcome::Cancelled | OperationOutcome::Undone(_) => {
24            Err(coven_database::DbError::Invariant {
25                what: "only storage setup is cancelled or undone",
26            }
27            .into())
28        }
29        // An invite ends this way, and no call waits for an invite's outcome.
30        OperationOutcome::SharingRefused { .. } => Err(coven_database::DbError::Invariant {
31            what: "only an invite ends with a sharing refusal",
32        }
33        .into()),
34    }
35}
36
37impl OperationKind {
38    /// The kind's name, as `coven_operations.kind` lists it.
39    pub fn listed(self) -> String {
40        match serde_json::to_value(self) {
41            Ok(serde_json::Value::String(name)) => name,
42            other => unreachable!("an operation kind is named by its variant: {other:?}"),
43        }
44    }
45}
46
47/// Reads `coven_operations.kind`.
48impl FromSql for OperationKind {
49    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
50        serde_json::from_value(serde_json::Value::String(value.as_str()?.to_owned()))
51            .map_err(|error| FromSqlError::Other(Box::new(error)))
52    }
53}