1#![allow(missing_docs)]
16
17use std::cmp::Ordering;
18use std::fmt::Debug;
19use std::fmt::Error;
20use std::fmt::Formatter;
21use std::hash::Hash;
22use std::hash::Hasher;
23use std::iter;
24use std::sync::Arc;
25
26use crate::backend::CommitId;
27use crate::op_store;
28use crate::op_store::OpStore;
29use crate::op_store::OpStoreResult;
30use crate::op_store::OperationId;
31use crate::op_store::OperationMetadata;
32use crate::op_store::ViewId;
33use crate::view::View;
34
35#[derive(Clone, serde::Serialize)]
38pub struct Operation {
39 #[serde(skip)]
40 op_store: Arc<dyn OpStore>,
41 id: OperationId,
42 #[serde(flatten)]
43 data: Arc<op_store::Operation>, }
45
46impl Debug for Operation {
47 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
48 f.debug_struct("Operation").field("id", &self.id).finish()
49 }
50}
51
52impl PartialEq for Operation {
53 fn eq(&self, other: &Self) -> bool {
54 self.id == other.id
55 }
56}
57
58impl Eq for Operation {}
59
60impl Ord for Operation {
61 fn cmp(&self, other: &Self) -> Ordering {
62 self.id.cmp(&other.id)
63 }
64}
65
66impl PartialOrd for Operation {
67 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
68 Some(self.cmp(other))
69 }
70}
71
72impl Hash for Operation {
73 fn hash<H: Hasher>(&self, state: &mut H) {
74 self.id.hash(state);
75 }
76}
77
78impl Operation {
79 pub fn new(
80 op_store: Arc<dyn OpStore>,
81 id: OperationId,
82 data: impl Into<Arc<op_store::Operation>>,
83 ) -> Self {
84 Self {
85 op_store,
86 id,
87 data: data.into(),
88 }
89 }
90
91 pub fn op_store(&self) -> Arc<dyn OpStore> {
92 self.op_store.clone()
93 }
94
95 pub fn id(&self) -> &OperationId {
96 &self.id
97 }
98
99 pub fn view_id(&self) -> &ViewId {
100 &self.data.view_id
101 }
102
103 pub fn parent_ids(&self) -> &[OperationId] {
104 &self.data.parents
105 }
106
107 pub fn parents(&self) -> impl ExactSizeIterator<Item = OpStoreResult<Self>> + use<'_> {
108 let op_store = &self.op_store;
109 self.data.parents.iter().map(|parent_id| {
110 let data = op_store.read_operation(parent_id)?;
111 Ok(Self::new(op_store.clone(), parent_id.clone(), data))
112 })
113 }
114
115 pub fn view(&self) -> OpStoreResult<View> {
116 let data = self.op_store.read_view(&self.data.view_id)?;
117 Ok(View::new(data))
118 }
119
120 pub fn metadata(&self) -> &OperationMetadata {
121 &self.data.metadata
122 }
123
124 pub fn stores_commit_predecessors(&self) -> bool {
128 self.data.commit_predecessors.is_some()
129 }
130
131 pub fn predecessors_for_commit(&self, commit_id: &CommitId) -> Option<&[CommitId]> {
133 let map = self.data.commit_predecessors.as_ref()?;
134 Some(map.get(commit_id)?)
135 }
136
137 pub fn all_referenced_commit_ids(&self) -> impl Iterator<Item = &CommitId> {
146 self.data.commit_predecessors.iter().flat_map(|map| {
147 map.iter()
148 .flat_map(|(new_id, old_ids)| iter::once(new_id).chain(old_ids))
149 })
150 }
151
152 pub fn store_operation(&self) -> &op_store::Operation {
153 &self.data
154 }
155}