1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
include!(concat!(env!("OUT_DIR"), "/patch.rs"));

use crate::{
    sdk::{
        commit::{CommitHash, CommitProof},
        events::{CheckedPatch, EventRecord},
    },
    Error, EventLogType, ProtoBinding, Result,
};

/// Request to patch an event log from a specific commit.
///
/// Used during auto merge to force push a combined collection
/// of events.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PatchRequest {
    /// Type of event log to patch.
    pub log_type: EventLogType,
    /// Hash of a commit to rewind to before
    /// applying the patch.
    pub commit: Option<CommitHash>,
    /// Proof for HEAD of the event log before the
    /// events are applied.
    pub proof: CommitProof,
    /// Patch of events to apply.
    pub patch: Vec<EventRecord>,
}

impl ProtoBinding for PatchRequest {
    type Inner = WirePatchRequest;
}

impl TryFrom<WirePatchRequest> for PatchRequest {
    type Error = Error;

    fn try_from(value: WirePatchRequest) -> Result<Self> {
        let commit = if let Some(commit) = value.commit {
            Some(commit.try_into()?)
        } else {
            None
        };

        let mut patch = Vec::with_capacity(value.patch.len());
        for event in value.patch {
            patch.push(event.try_into()?);
        }

        Ok(Self {
            log_type: value.log_type.unwrap().try_into()?,
            commit,
            proof: value.proof.unwrap().try_into()?,
            patch,
        })
    }
}

impl From<PatchRequest> for WirePatchRequest {
    fn from(value: PatchRequest) -> WirePatchRequest {
        Self {
            log_type: Some(value.log_type.into()),
            commit: value.commit.map(|c| c.into()),
            proof: Some(value.proof.into()),
            patch: value.patch.into_iter().map(|e| e.into()).collect(),
        }
    }
}

/// Response from a patch request.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PatchResponse {
    /// Checked patch status.
    pub checked_patch: CheckedPatch,
}

impl ProtoBinding for PatchResponse {
    type Inner = WirePatchResponse;
}

impl TryFrom<WirePatchResponse> for PatchResponse {
    type Error = Error;

    fn try_from(value: WirePatchResponse) -> Result<Self> {
        Ok(Self {
            checked_patch: value.checked_patch.unwrap().try_into()?,
        })
    }
}

impl From<PatchResponse> for WirePatchResponse {
    fn from(value: PatchResponse) -> WirePatchResponse {
        Self {
            checked_patch: Some(value.checked_patch.into()),
        }
    }
}