jj_lib/
operation.rs

1// Copyright 2020 The Jujutsu Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#![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::sync::Arc;
24
25use crate::op_store;
26use crate::op_store::OpStore;
27use crate::op_store::OpStoreResult;
28use crate::op_store::OperationId;
29use crate::op_store::OperationMetadata;
30use crate::op_store::ViewId;
31use crate::view::View;
32
33/// A wrapper around [`op_store::Operation`] that defines additional methods and
34/// stores a pointer to the `OpStore` the operation belongs to.
35#[derive(Clone)]
36pub struct Operation {
37    op_store: Arc<dyn OpStore>,
38    id: OperationId,
39    data: Arc<op_store::Operation>, // allow cheap clone
40}
41
42impl Debug for Operation {
43    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
44        f.debug_struct("Operation").field("id", &self.id).finish()
45    }
46}
47
48impl PartialEq for Operation {
49    fn eq(&self, other: &Self) -> bool {
50        self.id == other.id
51    }
52}
53
54impl Eq for Operation {}
55
56impl Ord for Operation {
57    fn cmp(&self, other: &Self) -> Ordering {
58        self.id.cmp(&other.id)
59    }
60}
61
62impl PartialOrd for Operation {
63    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
64        Some(self.cmp(other))
65    }
66}
67
68impl Hash for Operation {
69    fn hash<H: Hasher>(&self, state: &mut H) {
70        self.id.hash(state);
71    }
72}
73
74impl Operation {
75    pub fn new(
76        op_store: Arc<dyn OpStore>,
77        id: OperationId,
78        data: impl Into<Arc<op_store::Operation>>,
79    ) -> Self {
80        Operation {
81            op_store,
82            id,
83            data: data.into(),
84        }
85    }
86
87    pub fn op_store(&self) -> Arc<dyn OpStore> {
88        self.op_store.clone()
89    }
90
91    pub fn id(&self) -> &OperationId {
92        &self.id
93    }
94
95    pub fn view_id(&self) -> &ViewId {
96        &self.data.view_id
97    }
98
99    pub fn parent_ids(&self) -> &[OperationId] {
100        &self.data.parents
101    }
102
103    pub fn parents(&self) -> impl ExactSizeIterator<Item = OpStoreResult<Operation>> + use<'_> {
104        let op_store = &self.op_store;
105        self.data.parents.iter().map(|parent_id| {
106            let data = op_store.read_operation(parent_id)?;
107            Ok(Operation::new(op_store.clone(), parent_id.clone(), data))
108        })
109    }
110
111    pub fn view(&self) -> OpStoreResult<View> {
112        let data = self.op_store.read_view(&self.data.view_id)?;
113        Ok(View::new(data))
114    }
115
116    pub fn metadata(&self) -> &OperationMetadata {
117        &self.data.metadata
118    }
119
120    pub fn store_operation(&self) -> &op_store::Operation {
121        &self.data
122    }
123}